Вопрос:

Can a two-dimensional array in C be initialized without explicit size?

c arrays gcc initialization

8188 просмотра

5 ответа

723 Репутация автора

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

Автор: Wojciech Gac Источник Размещён: 28.02.2014 04:19

Ответы (5)


0 плюса

4571 Репутация автора

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.

Автор: Rikayan Bandyopadhyay Размещён: 28.02.2014 04:25

-1 плюса

1 Репутация автора

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.

Автор: Jakeloyd Размещён: 28.02.2014 04:44

0 плюса

13541 Репутация автора

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.

Автор: Lee Duhem Размещён: 28.02.2014 05:31

2 плюса

7846 Репутация автора

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);
Автор: jilles Размещён: 28.02.2014 11:12

0 плюса

8 Репутация автора

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

Автор: fahim Размещён: 26.05.2014 04:58
Вопросы из категории :
32x32