C语言中的可变大小矩阵

C语言中的可变大小矩阵,c,dynamic,size,C,Dynamic,Size,创建一个大小为n的单脚本浮点数组。我可以为双脚本数组做一些类似的事情吗?在这方面有一个很好的章节。您可以为多维数组做几乎相同的事情 float **array; array = calloc(sizeof(float*), n); for(int i = 0; i < n; i++) { array[i] = calloc(sizeof(float), n); } float**数组; 数组=calloc(sizeof(float*),n; 对于(int i=0;i3。这有点误导

创建一个大小为n的单脚本浮点数组。我可以为双脚本数组做一些类似的事情吗?

在这方面有一个很好的章节。

您可以为多维数组做几乎相同的事情

float **array;
array = calloc(sizeof(float*), n);
for(int i = 0; i < n; i++)
{
    array[i] = calloc(sizeof(float), n);
}
float**数组;
数组=calloc(sizeof(float*),n;
对于(int i=0;i
如果您想要一个包含n行和m列的矩阵,那么可以使用长度为
m*n
的线性数组来表示,其中每个索引
i
表示

row = i  / n
col = i  % n
以及逆映射

i  = row * n  + col

大多数使用矩阵(如matlab)的代数软件包实际上都使用这种表示法,因为它可以很好地推广到任何维度(您也可以将其推广到三维矩阵)。

C中没有双脚本数组;只有数组的数组。例如,这:

int a[3][3];
应读作“3个3整数数组的数组”,而不是“3x3整数数组”。这可以从表达式类型中立即看到,例如,
a[0]
是有效的表达式,其类型为
int[3]

对于数组类型,数组大小是类型的一部分,因此必须在编译时知道。因此,虽然您可以使用“指向数组的指针”类型使一维成为动态的,但其余的类型仍然必须是固定的:

int (*p)[3] // pointer to arrays of 3 ints each
有两种传统的解决办法:

  • 只需使用宽度x高度元素的一维动态数组,并根据2D坐标计算1D索引,如
    (y*width+x)
    所示

  • 使用指向指针的指针:

    int** a = malloc(sizeof(int*) * height);
    for (i = 0; i < height; ++i) a[i] = malloc(sizeof(int) * width);
    a[0][0] = 123;
    ...
    

    不,那是不可能的。或者,分配一个数组,并定义一个索引函数,该函数获取坐标并将索引返回到数组中

    int Index(int i, int j, int numCols)
    { 
        return i * numCols + j;
    }
    
    int numRows = 100;
    int numCols = 200;
    
    float *data = malloc(sizeof(float) * numRows * numCols);
    
    data[Index(34, 56, numCols)] = 42.0f;
    

    您可以使用C99可变长度数组(与gcc配合使用):

    #包括
    #包括
    void foo(行大小、列大小、浮点数组[行][列])
    {
    printf(“%f\n”,数组[2][3]);
    }
    内部主(空)
    {
    行的大小=4;
    尺寸=5;
    float(*array)[cols]=calloc(sizeof(float),行*cols);
    数组[2][3]=42;
    foo(行、列、数组);
    }
    
    我很惊讶没有人指出“明显的”替代方案,它保留了主矩阵的单个连续分配,但有指针向量来提供双下标。(我想这意味着这并不明显。)


    显然,我们还需要检查内存分配。

    在这一点上,我可以调用array[2][3]=5吗?当然,假设n>3。这有点误导——一个二维数组
    double[][]
    占用一个内存段,而它为每行存储指向段的指针数组。当然,您仍然可以使用数组下标访问它,但它肯定不是同一回事。@wolfPack88:是的,但您一定要了解它是如何工作的
    array[2]
    是存储在数组中的第三个
    float*
    指针,而
    array[3]
    接受存储在
    array[2]
    指向的内存中的第四个
    float
    指针:这增加了允许可变长度行的灵活性。对于矩阵的数学概念建模来说,这不是必需的,但可能很有用。@Jefromi这是真的,但您可以做类似的事情,并拥有连续的内存。“您可以使用C99可变长度数组。”但请不要使用:)@鲍比:如果你的编译器支持它们,我看不出有什么理由不支持它们——特别是在这样一个不涉及堆栈分配的情况下……我想你的意思是*(数据+34*200+56)=42.0f。。。我通常更喜欢读写风格。在第二种方法中,您不需要对数组的每一行执行一次
    malloc
    ——您仍然可以在一个大的块中分配它,然后将行指针分配到该分配中的位置。有关选项1的额外示例,请参见我的回答
    int Index(int i, int j, int numCols)
    { 
        return i * numCols + j;
    }
    
    int numRows = 100;
    int numCols = 200;
    
    float *data = malloc(sizeof(float) * numRows * numCols);
    
    data[Index(34, 56, numCols)] = 42.0f;
    
    #include <stdio.h>
    #include <stdlib.h>
    
    void foo(size_t rows, size_t cols, float array[rows][cols])
    {
        printf("%f\n", array[2][3]);
    }
    
    int main(void)
    {
        size_t rows = 4;
        size_t cols = 5;
        float (*array)[cols] = calloc(sizeof (float), rows * cols);
        array[2][3] = 42;
        foo(rows, cols, array);
    }
    
    float **array2d = malloc(sizeof(*array2d) * height);
    float  *array1d = malloc(sizeof(*array1d) * height * width);
    
    for (i = 0; i < height; ++i)
        array2d[i] = &array1d[i * width];
    
    array2d[0][0] = 123.0;