Main Content

本页翻译不是最新的。点击此处可查看最新英文版本。

为代码生成定义可变大小数据

对于代码生成,在运算中使用变量或以输出形式返回变量之前,必须为它们分配特定的类、大小和复/实性。通常,在初始分配后,您便无法再重新分配变量属性。因此,在为变量或结构体字段分配固定大小后,尝试增大变量或结构体字段可能会导致编译错误。在这些情况下,您必须使用以下方法之一将数据显式定义为可变大小。

方法参阅

从可变大小矩阵构造函数中分配数据,例如:

使用具有非常量维度的矩阵构造函数
在使用(读取)变量之前为同一变量分配多个常量大小。为同一个变量分配多个大小
使用 (end + 1) 索引增大数组。使用 (end + 1) 增大数组
将变量的所有实例定义为可变大小。使用 coder.varsize 显式定义可变大小数据

注意

如果其中一个变量使用别名类型并且大小可变,则 MATLAB Function 模块不支持代码生成。此限制不适用于输入或输出变量。有关在 MATLAB Function 模块中定义可变大小变量的详细信息,请参阅Create and Define MATLAB Function Block Variables声明可变大小的 MATLAB Function 模块变量

使用具有非常量维度的矩阵构造函数

您可以通过使用具有非常量维度的构造函数来定义可变大小矩阵。例如:

function s = var_by_assign(u) %#codegen
y = ones(3,u);
s = numel(y);

如果不使用动态内存分配,还必须添加 assert 语句来提供维度的上界。例如:

function s = var_by_assign(u) %#codegen
assert (u < 20);
y = ones(3,u);
s = numel(y);

为同一个变量分配多个大小

在代码中使用(读取)变量之前,可以通过为其分配多个恒定大小来使其大小可变。当代码生成器在堆栈上使用静态分配时,它会根据为每个维度指定的最大大小来推断上界。当您在所有分配中为给定的维度分配相同的大小时,代码生成器假定该维度固定为该大小。通过这些分配可以指定不同的形状和大小。

当代码生成器使用动态内存分配时,它不检查上界。它假设可变大小数据是无界的。

从多个不同形状的定义推断上界

function s = var_by_multiassign(u) %#codegen
if (u > 0)
    y = ones(3,4,5);
else
    y = zeros(3,1);
end
s = numel(y);

当代码生成器使用静态分配时,它推断 y 是三维矩阵:

  • 第一个维度的大小固定为 3

  • 第二个维度为可变大小,上界为 4

  • 第三个维度为可变大小,上界为 5

当代码生成器使用动态分配时,它会以不同方式分析 y 的维度:

  • 第一个维度的大小固定为 3。

  • 第二个和第三个维度是无界的。

使用 (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 的数组时,才支持增大该数组。

使用 coder.varsize 显式定义可变大小数据

要显式定义可变大小数据,请使用函数 coder.varsize。您也可以指定哪些维度大小可变及其上界。例如:

  • B 定义为可变大小的二维数组,其中每个维度的上界为 64。

    coder.varsize('B', [64 64]);

  • B 定义为可变大小数组:

    coder.varsize('B');

    如果您仅提供第一个参数,coder.varsize 将假设 B 的所有维度都是可变的,并且上界为 size(B)

如果 MATLAB Function 模块的输出信号是可变大小的,则您必须在属性检查器中指定该信号是可变大小的。您可以指定上界或将变量定义为无界 (自 R2023b 起)。不要求一定对 MATLAB Function 模块内的对应输出变量使用 coder.varsize。但是,如果使用 coder.varsize 指定上界,则它们必须与属性检查器中的上界匹配。

指定哪些维度可变

您可以使用函数 coder.varsize 来指定哪些维度是可变的。例如,以下语句将 B 定义为数组,其第一个维度固定为 2,但其第二个维度可以增长到 16:

coder.varsize('B',[2, 16],[0 1])
.

第三个参数指定哪些维度是可变的。此参数必须为逻辑向量或只包含 0 和 1 的双精度向量。对应于零或 false 的维度具有固定大小。对应于 1 或 true 的维度的大小是可变的。coder.varsize 通常将大小为 1 的维度视为固定大小。请参阅用单一维度定义可变大小矩阵

定义固定维度后允许增大变量大小

函数 var_by_if 定义矩阵 Y,在第一次使用前具有固定的 2×2 维度(其中语句 Y = Y + uY 读取)。但是,coder.varsizeY 定义为可变大小矩阵,允许它根据 else 子句中的决策逻辑来更改大小:

function Y = var_by_if(u) %#codegen
if (u > 0)
    Y = zeros(2,2);
    coder.varsize('Y');
    if (u < 10)
        Y = Y + u;
    end
else
    Y = zeros(5,5);
end

如果没有 coder.varsize,代码生成器会推断 Y 是固定大小的 2×2 矩阵。它会生成大小不匹配的错误。

用单一维度定义可变大小矩阵

单一维度是 size(A,dim) = 1 的维度。在下列情况下,单一维度的大小是固定的:

  • 您在 coder.varsize 表达式中指定上界为 1 的维度。

    例如,在此函数中,Y 的行为类似于具有一个可变大小维度的向量:

    function Y = dim_singleton(u) %#codegen
    Y = [1 2];
    coder.varsize('Y', [1 10]);
    if (u > 0)
        Y = [Y 3];
    else
        Y = [Y u];
    end
    

  • 您使用矩阵构造函数表达式或矩阵函数初始化具有单一维度的可变大小数据。

    例如,在此函数中,XY 的行为类似于向量,其中只有其第二个维度的大小是可变的。

    function [X,Y] = dim_singleton_vects(u) %#codegen
    Y = ones(1,3);
    X = [1 4];
    coder.varsize('Y','X');
    if (u > 0)
        Y = [Y u];
    else
        X = [X u];
    end

您可以通过使用 coder.varsize 显式指定单一维度可变来覆盖此行为。例如:

function Y = dim_singleton_vary(u) %#codegen
Y = [1 2];
coder.varsize('Y', [1 10], [1 1]);
if (u > 0)
    Y = [Y Y+u];
else
    Y = [Y Y*u];
end

在此示例中,coder.varsize 的第三个参数是由 1 组成的向量,表示 Y 的每个维度的大小可变。

定义可变大小结构体字段

要将结构体字段定义为可变大小数组,请使用冒号 (:) 作为索引表达式。冒号 (:) 表示数组的所有元素的大小都是可变的。例如:

function y=struct_example() %#codegen

d = struct('values', zeros(1,0), 'color', 0);
data = repmat(d, [3 3]);
coder.varsize('data(:).values');

for i = 1:numel(data)
    data(i).color = rand-0.5;
    data(i).values = 1:i;
end

y = 0;
for i = 1:numel(data)
    if data(i).color > 0
        y = y + sum(data(i).values);
    end
end

表达式 coder.varsize('data(:).values') 将矩阵 data 的每个元素中的字段 values 定义为可变大小。

以下是其他示例:

  • coder.varsize('data.A(:).B')

    在此示例中,data 是包含矩阵 A 的标量变量。矩阵 A 的每个元素都包含大小可变的字段 B

  • coder.varsize('data(:).A(:).B')

    此表达式将矩阵 Adata 的每个元素内的字段 B 定义为可变大小。

另请参阅

相关主题