C中的可变大小的矩阵

时间:2009-10-30 17:14:59

标签: c dynamic size

有没有办法在C中创建一个可变大小的双脚本数组(不是C ++,只是C)?我知道要创建一个可变大小的单脚本数组,只需使用指针,例如

float *array;
array = (float *) calloc(sizeof(float), n);

创建一个单一脚本的大小为n的浮点数组。是否有类似于我可以为双重脚本数组做的事情?

7 个答案:

答案 0 :(得分:10)

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

int a[3][3];

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

对于数组类型,数组大小是类型的一部分,因此必须在编译时知道。因此,虽然您可以使用“指向数组的指针”类型来使一个维度动态化,但其余维度仍然需要修复:

int (*p)[3] // pointer to arrays of 3 ints each

有两种传统的解决方法:

  1. 只需使用 width x height 元素的一维动态数组,并自己计算2D坐标的1D索引为(y * width + x)。< / p>

  2. 使用指针指针:

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

    这里的问题是你的阵列不再是矩形了,你无法真正强制执行它。在性能方面,它也比单个连续的内存块更糟糕。

  3. 在C99中,您还可以使用可变长度数组:

    void foo(int width, int height) {
        int a[width][height];
        ...
    }
    

答案 1 :(得分:6)

comp.lang.c FAQ有一个很好的部分。

答案 2 :(得分:5)

对于多维数组,你可以做几乎相同的事情。

float **array;
array = calloc(sizeof(float*), n);
for(int i = 0; i < n; i++)
{
    array[i] = calloc(sizeof(float), n);
}

答案 3 :(得分:4)

如果您想要一个包含n行和m列的矩阵,那么您可以使用长度为m*n的线性数组来表示这一点,其中每个索引i代表

row = i  / n
col = i  % n

和逆映射

i  = row * n  + col

使用像matlab这样的矩阵的大多数代数包实际上都使用这种表示法,因为它可以很好地推广到任何维度(你可以将它概括为三维矩阵)。

答案 4 :(得分:2)

不,那是不可能的。作为替代方案,分配单个数组,并定义索引函数,该函数获取坐标并将索引返回到数组中。

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;

答案 5 :(得分:1)

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

#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);
}

答案 6 :(得分:1)

我很惊讶没有人指出“明显的”替代方案,它保留了主矩阵的单个连续分配,但是有一个指针向量可以给出双重下标。 (我想这毕竟意味着它并不明显。)

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;

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