主要内容

为具有 end + 1 索引的增大数组和元胞数组生成代码

通过使用 end + 1 索引,代码生成支持在 MATLAB® 代码中增大数组或元胞数组。默认情况下,代码生成支持可变大小数组。要验证此功能是否启用,请使用以下方法之一:

  • 在代码配置对象中,确保属性 EnableVariableSizing 设置为 true

  • 在“代码生成设置”对话框中,确保启用可变大小复选框处于选中状态。

使用 (end + 1) 索引增大数组

要增大数组 X,可以为 X(end + 1) 赋值。如果您在 MATLAB 代码中进行这种赋值,代码生成器会将您增大的维度视为可变大小维度。

例如,您可以为以下代码片段生成代码:

...
a = [1 2 3 4 5 6];
a(end + 1) = 7;

b = [1 2];
for i = 3:10
    b(end + 1) = i;
end
...

使用 (end + 1) 增大数组时,请遵循以下限制:

  • 仅使用 (end + 1)。不要使用 (end + 2)(end + 3) 等。

  • 仅对向量使用 (end + 1)。例如,不允许使用以下代码,因为 X 是矩阵,而不是向量。

    ...
    X = [1 2; 3 4];
    X(end + 1) = 5;
    ...
  • 您可以使用 (end + 1) 增大大小为 1x0 的空数组。不支持增大大小为 0x1 的数组。仅当使用 [] 创建大小为 0x0 的数组时,才支持增大该数组。

增大在运行时初始化为标量的可变大小列数组

在 MATLAB 执行中,如果您使用 (end+1) 索引来增大标量数组,则数组将沿第二个维度增大并生成一个行向量。例如,定义函数 grow

function z = grow(n, m)
n(end+1) = m;
z = n;
end

使用示例输入调用 grow

grow(2,3)
ans =

     2     3

相反,在代码生成中,假设:

  • 您在编译时将数组指定为可变大小的列类型(例如,:Inf x 1),并且

  • 在运行时将此数组初始化为标量。

在这种情况下,生成的代码尝试沿第一个维度增大标量,因此会产生运行时错误。例如,为 grow 生成 MEX 代码。将输入 n 指定为 :Inf x 1 双精度数组。将输入 m 指定为双精度标量。

codegen grow -args {coder.typeof(0, [Inf 1], [1 0]), 1}
Code generation successful.

使用与之前相同的输入运行生成的 MEX。

grow_mex(2,3)

Attempted to grow a scalar along the first dimension using end+1 indexing.This behavior differs from MATLAB execution which grows a scalar along the second dimension.(已尝试使用 end+1 索引沿第一个维度增大标量。此行为不同于 MATLAB 执行,后者会沿第二个维度增大标量。)

如何避免此错误.  要避免此错误并在生成的代码和 MATLAB 执行中沿列维度增大数组,请以如下方式之一重写 MATLAB 代码:

  • 使用串联运算符(而不是使用 (end+1))增大数组。例如,将 grow 函数重写为:

    function z = growCat(n, m)
    n = [n;m];
    z = n;
    end
  • 在函数中,通过转置要增长的变量来创建一个临时变量。然后,使用 (end+1) 索引增大此临时变量。最后,对此临时变量进行第二次转置。例如,将 grow 函数重写为:

    function z = growTransposed(n, m)
    temp = n';
    temp(end+1) = m;
    z = temp';
    end

使用 {end + 1} 索引增大元胞数组

要增大元胞数组 X,可以使用 X{end + 1}。例如:

...
X = {1 2};
X{end + 1} = 'a';
...

当您使用 {end + 1} 增大元胞数组时,请遵循以下限制:

  • MATLAB Function (Simulink) 模块中,不要在 for 循环中使用 {end + 1}

  • 仅使用 {end + 1}。不要使用 {end + 2}{end + 3} 等。

  • 仅对向量使用 {end + 1}。例如,不允许使用以下代码,因为 X 是矩阵,而不是向量:

    ...
    X = {1 2; 3 4};
    X{end + 1} = 5;
    
    ...

  • 仅对变量使用 {end + 1}。在以下代码中,{end + 1} 不会使 {1 2 3} 增大。在本例中,代码生成器将 {end + 1} 视为超出 X{2} 范围的索引。

    ...
    X = {'a' { 1 2 3 }};
    X{2}{end + 1} = 4;
    ...

  • {end + 1} 在循环中增大元胞数组时,该元胞数组必须是可变大小的。因此,元胞数组必须是同构元胞数组

    允许使用以下代码,因为 X 是同构元胞数组。

    ...
    X = {1  2};
    for i=1:n
        X{end + 1} = 3;
    end
    ...

    不允许使用以下代码,因为 X 是异构元胞数组。

    ...
    X = {1 'a' 2 'b'};
    for i=1:n
        X{end + 1} = 3;
    end
    ...

  • 有关导致生成的代码和 MATLAB 之间行为差异的编码模式,请参阅增大在运行时初始化为标量的可变大小列元胞数组