无法确定元胞数组的每个元素都已赋值
问题
您会看到以下消息之一:
Unable to determine that every element of 'y' is assigned before this line.
Unable to determine that every element of 'y' is assigned before exiting the function.
Unable to determine that every element of 'y' is assigned before exiting the recursively called function.
原因
对于代码生成,在使用某元胞数组元素之前,必须为其赋值。当您使用 cell
创建可变大小元胞数组(例如 cell(1,n)
)时,MATLAB® 会用一个空矩阵对每个元素赋值。然而,代码生成并不会对元素进行赋值。对于代码生成,在您使用 cell
创建可变大小元胞数组后,必须对该元胞数组的所有元素赋值,然后才能使用该元胞数组。
在首次使用元胞数组之前,代码生成器会分析您的代码,以确定是否所有元素均已赋值。当代码遵循以下模式时,代码生成器会检测到所有元素都已赋值:
function z = CellVarSize1D(n, j) %#codegen x = cell(1,n); for i = 1:n x{i} = i; end z = x{j}; end
以下是针对多维元胞数组的模式:
function z = CellAssign3D(m,n,p) %#codegen x = cell(m,n,p); for i = 1:m for j =1:n for k = 1:p x{i,j,k} = i+j+k; end end end z = x{m,n,p}; end
如果代码生成器检测到某些元素未赋值,代码生成将失败。有时,尽管您的代码对元胞数组的所有元素进行了赋值,代码生成也会失败,因为分析没有检测到所有元素都赋值。
以下是代码生成器无法检测到元素已赋值的示例:
元素在不同循环中赋值
... x = cell(1,n) for i = 1:5 x{i} = 5; end for i = 6:n x{i} = 7; end ...
定义循环结束值的变量与定义元胞维度的变量不同。
... x = cell(1,n); m = n; for i = 1:m x{i} = 2; end ...
有关详细信息,请参阅使用 cell 定义可变大小元胞数组。
解决方法
尝试以下解决方法之一:
使用可识别的模式为元素赋值
如果可能,重写您的代码以遵循以下模式:
... x = cell(1,n); for i = 1:n x{i} = i; end z = x{j}; ...
使用 repmat
有时,您可以使用 repmat
来定义可变大小的元胞数组。
以如下定义可变大小元胞数组的代码为例。它将 1 赋值给奇数元素,将 2 赋值给偶数元素。
function z = repDefine(n, j) %#codegen c =cell(1,n); for i = 1:2:n-1 c{i} = 1; end for i = 2:2:n c{i} = 2; end z = c{j};
代码生成不允许以下代码,因为:
多个循环为元素赋值。
循环计数器不是按 1 递增。
重写代码,首先使用 cell
创建第一个元素为 1,第二个元素为 2 的 1×2 元胞数组。然后,使用 repmat
创建一个可变大小的元胞数组,其元素值在 1 和 2 之间交替。
function z = repVarSize(n, j) %#codegen c = cell(1,2); c{1} = 1; c{2} = 2; c1= repmat(c,1,n); z = c1{j}; end
您可以使用 repmat
将初始为空的可变大小元胞数组传入或传出函数。使用以下模式:
function x = emptyVarSizeCellArray x = repmat({'abc'},0,0); coder.varsize('x'); end
以下代码表示 x
是由 1x3
个字符组成的空的可变大小元胞数组,可以传入或传出函数。
使用 coder.nullcopy
最后,您还可以使用 coder.nullcopy
来指示代码生成器可以为元胞数组分配内存,而无需初始化内存。例如:
function z = nulcpyCell(n, j) %#codegen c =cell(1,n); c1 = coder.nullcopy(c); for i = 1:4 c1{i} = 1; end for i = 5:n c1{i} = 2; end z = c1{j}; end
请慎用 coder.nullcopy
。如果访问未初始化的内存,结果是不可预测的。
另请参阅
cell
| repmat
| coder.nullcopy