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 a
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.
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.
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.
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);
No you can't do it. If you even don't initialize, you can't define an int array[][];