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
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:
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:
Then the following macro deduces the second dimension from the first row:
It only works if there are at least two rows.
Example:
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:
called as:
No you can't do it. If you even don't initialize, you can't define an int array[][];
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.
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
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 likeCompiler needs this
COL
to do proper pointer arithmetic infoo()
.Usually, we define
COL
as a macro that will be replaced by an integer in a header file, and use it in the definitions ofmulti_array
andfoo()
: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.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.