可以在没有明确大小的情况下初始化C中的二维数组吗?

时间:2014-02-28 16:19:24

标签: c arrays gcc initialization

我对C中的二维数组有疑问。我现在知道(从直接编译器经验)我不能像这样一维数组初始化这样的数组:

int multi_array[][] = {
  {1,2,3,4,5},
  {10,20,30,40,50},
  {100,200,300,400,500}
};

> compiler output:

gcc -o arrays arrays.c
arrays.c: In function ‘main’:
arrays.c:8:9: error: array type has incomplete element type

最接近的解决方案是明确提供列数:

int multi_array[][5] = {
  {1,2,3,4,5},
  {10,20,30,40,50},
  {100,200,300,400,500}
};

我的问题是:它可以整齐地完成吗?没有显式提供数字(毕竟编译器应该能够推断自己)?我不是在谈论用malloc或其他东西手动构建它,而是与我尝试的东西接近。 另外,对C编译器有所了解的人可以从低级别的角度解释为什么我的初始尝试不起作用吗?

我使用普通gcc而没有非标准选项来编译代码。

由于

5 个答案:

答案 0 :(得分:2)

您可以使用C99复合文字功能执行此操作。

部分想法是初始化列表的长度可以这样确定:

sizeof (int[]){ 1, 2, 3, 4, 5 } / sizeof(int)

我们需要一个解决方法,因为你可以将包含逗号的参数传递给宏的唯一方法是将括号放在参数的一部分(

#define ROW(...) { __VA_ARGS__ }

然后,下面的宏推断出第一行的第二个维度:

#define MAGIC_2DARRAY(type, ident, row1, ...) \
        type ident[][sizeof (type[])row1 / sizeof (type)] = { \
                row1, __VA_ARGS__ \
        }

仅在至少有两行时才有效。

示例:

MAGIC_2DARRAY(int, arr, ROW(7, 8, 9), ROW(4, 5, 6));

你可能不想在真正的程序中使用它,但它是可能的。

为了将这种数组传递给函数,C99可变长度数组功能很有用,具有如下函数:

void printarr(int rows, int columns, int array[rows][columns]) { ... }

称为:

printarr(sizeof arr / sizeof arr[0], sizeof arr[0] / sizeof arr[0][0], arr);

答案 1 :(得分:1)

C中的2D数组存储在连续的内存位置。因此,如果您不提供行数或列数,编译器将如何知道有多少行和列?

对于row major matrix,行内容位于连续的内存位置。所以你需要至少指定列数。类似地,对于列主矩阵,您需要至少指定行数。无论是行专业还是列专业都是由架构定义的。看来你所拥有的是一个主要的行架构。

答案 2 :(得分:0)

使用1d数组创建结构。但是,如果您遵循此方法,您可以创建新数组,但它将是一个函数调用来更改大小和值。动态矩阵方法可以接近解决您的问题。

答案 3 :(得分:0)

在原帖中没有直接回答这些问题,我只想指出提问者提出的建议可能不是一个好的或有用的想法。


编译器确实可以从

推断出来
int multi_array[][] = {
  {1,2,3,4,5},
  {10,20,30,40,50},
  {100,200,300,400,500}
};

multi_array的结构。

但是当你想要声明和定义一个函数(这个声明和定义可以在另一个编译单元或源文件中),假设接受multi_array作为其参数之一时,你仍然需要做类似的事情。

int foo(..., int multi_array[][COL], ...) { }

编译器需要此COLfoo()中执行正确的指针算法。

通常,我们将COL定义为一个宏,它将被头文件中的整数替换,并在multi_arrayfoo()的定义中使用它:

int multi_array[][COL] = { ... };

int foo(..., int multi_array[][COL], ...) { }

通过这样做,很容易确保它们是相同的。让编译器根据它的初始化来推断multi_array的结构,当你给它一个错误的初始化时,你实际上在代码中引入了一个bug。

答案 4 :(得分:0)

不,你不能这样做。如果你甚至没有初始化,你就无法定义一个int数组[] [];