Can a two-dimensional array in C be initialized wi

2020-03-11 02:10发布

I have a question regarding two-dimensional arrays in C. I know now (from direct compiler experience) that I can't initialize such an array analogously to one-dimensional arrays like this:

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

The closest solution that works is to provide the number of columns explicitly like this:

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

My question is: can it be done neatly without supplying the number explicitly (which after all the compiler should be able to infer itself)? I'm not talking about manually constructing it with malloc or something but rather something close to what I tried. Also, can someone knowledgeable about C compilers explain from a low-level perspective why my initial attempt does not work?

I used plain gcc with no non-standard options to compile the code.

Thanks

5条回答
干净又极端
2楼-- · 2020-03-11 02:18

You can do this using the C99 compound literal feature.

A partial idea is that the length of an initializer list can be determined like this:

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

We need a workaround for the fact that the only way you can pass an argument containing a comma to a macro is to put parentheses around (part of) the argument:

#define ROW(...) { __VA_ARGS__ }

Then the following macro deduces the second dimension from the first row:

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

It only works if there are at least two rows.

Example:

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

You probably do not want to use this in a real program, but it is possible.

For passing this kind of array to functions, the C99 variable length array feature is useful, with a function like:

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

called as:

printarr(sizeof arr / sizeof arr[0], sizeof arr[0] / sizeof arr[0][0], arr);
查看更多
再贱就再见
3楼-- · 2020-03-11 02:20

No you can't do it. If you even don't initialize, you can't define an int array[][];

查看更多
够拽才男人
4楼-- · 2020-03-11 02:24

Create a structure with 1d arrays. However, if you follow this method you can create new arrays but it will be a function call to change sizes and values. A dynamic matrix approach could come close to solving your issue.

查看更多
闹够了就滚
5楼-- · 2020-03-11 02:30

Not a direct answer to those questions in the original post, I just want to point out that what the asker propose may be not such a good or useful idea.


The compiler indeed can infer from

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

the structure of multi_array.

But when you want to declare and define a function (this declaration and definition could be in another compilation unit or source file) that supposes to accept multi_array as one of its argument, you still need to do something like

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

Compiler needs this COL to do proper pointer arithmetic in foo().

Usually, we define COL as a macro that will be replaced by an integer in a header file, and use it in the definitions of multi_array and foo():

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

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

By doing this, it is easy to make sure they are the same. And let compiler to infer the structure of multi_array according to its initialization, when you give it a wrong initialization, you actually introduce a bug in your code.

查看更多
一纸荒年 Trace。
6楼-- · 2020-03-11 02:30

2D arrays in C are stored in contiguous memory locations. So if you do not provide the number of rows or the number of columns, how will the compiler know how many rows and column there are?

For a row major matrix, rows contents are at contiguous memory positions. So you need to specify at least the number of columns. Similarly for a column major matrix, you need to specify at least the number of rows. Whether it is row major or column major is defined by architecture. It seems that what you have is a row major architecture.

查看更多
登录 后发表回答