C中每行具有不同大小的二维数组

2D array with different size for each line in C

我想知道是否可以在 C 中创建具有不同线条大小的二维数组。

我知道二维数组是存储其他数组的数组。但是如果数组大小不同怎么办? 像这样(一个"T"是数组可用的位置)

   0  1  2  3  4
0  T  T  
1  T  T  T  T  T
2  T  T  T
3  T  T  T  T  

如果可以,怎么做?就像普通的二维数组一样?

我猜你指的是指向指针的指针。 (以后请尽量使用合适的标签标识,点击标签即可查看)

但是是的!没有什么能阻止你做:

int **pointerToPointers = malloc(length*sizeof(int *));
pointerToPointers[xUnderLength] = malloc(arbitaryLength*sizeof(int));

当然你可以创建这样的结构,但你必须determine/save 每行的列数。例如

size_t cols_per_row [] = { 2, 5, 3, 4 };

int **arr2d = calloc(sizeof cols_per_row / sizeof *cols_per_row, sizeof *arr2d);

for(size_t i = 0; i < sizeof cols_per_row / sizeof *cols_per_row; ++i)
    arr2d[i] = calloc(cols_per_row[i], sizeof *arr2d[i]);

我省略了 when calloc returns NULL 的错误检查,以便在更少的行中演示原理。

请注意,我使用 calloc 而不是 malloc,因为 calloc 将内存设置为 0,这有利于初始化。

IMO 最好的解决方案确实是制作以下类型结构的数组:

struct arbitrary_len_arr {
    int len;
    int* arr;
};

这个实现的美妙之处在于,一旦你让你的二维数组使用这些结构作为每一行的指针,你就可以更新你的 arr 指针以指向你想要的任何数组长度,只要你更新它的 len 成员。所以你会做的是:

struct arbitrary_len_arr* my_arr = malloc(sizeof(struct arbitrary_len_arr) * N);

其中 N 是您想要的行数。然后,当您填充它们时,您还必须相应地填充成员,如下所示:

my_arr[i].len = M;
my_arr[i].arr = malloc(sizeof(int) * M;

可能在某个循环中。然后你将拥有任意长度的数组。

不同大小的数组的数组在 C 中是可能的。简单地说,它们不是二维数组,而是数组或指针。您将从 C 标签常见问题解答中找到更多关于 的区别。

@vahero 展示了如何动态分配它,但也可以使用静态或自动存储:

char row0[] = "TT";      // size 3 because of the terminating null...
char row1[] = "TTTTT";
char row2[] = "TTT";
char row3[] = "TTTT";
char* array[] = { row0, row1, row2, row3};

或者没有额外的变量标识符:

char *arr[] = { 
    (char[]){ 'T', 'T', 0 },
    (char[]){ 'T', 'T', 'T', 'T', 'T', 0 },
    (char[]){ 'T', 'T', 'T', 0 },
    (char[]){ 'T', 'T', 'T', 'T', 0 },
};

然后您可以照常使用:

for (int i=0; i<sizeof(arr)/sizeof(arr[0]); i++) {
    for(int j=0; arr[i][j] != '[=12=]'; j++) {
        printf("%c ", arr[i][j]);
    }
    printf("\n");
}

如果您的意思是您可以声明一个维度具有可变大小的元素,那么答案是否定的。 C 不支持动态调整大小的结构,因此如果不缩放最大元素的 space,就不能将它们分配到数组中。但是,方法和手段是有的。你可以分配一个 space 的块,只使用你需要的,效率不高。您可以使用联合来拥有各种类型但大小固定的元素。最主要的是你在 C 中有一个固定的步幅值,所以元素都需要符合这个步幅值。也就是说,如果数据要进入数组结构。

上述解决方案提出了另一种解决方案,即您的结构存储指向存储在别处的数据的指针。在我看来,这不是您要问的,但这是解决问题的方法。您可以存储指向按需分配的数据元素的链接。然后,数组更像是一个索引而不是存储结构。我通常在 MISRA 等非动态分配环境中操作。如果我说某些东西必须是 "in" 数组,我会假设您指的是该对象定义的内存中的所有数据。所以答案是否定的,如果你愿意让数据被索引......嗯是的......如果你很高兴浪费了 space,再一次,是的......但不是打包变量C 数组对象中的大小数据元素。