Reputation: 350
My intuition when I see this int array_name[x][y];
is an array of y
arrays i.e. array_name[x]
is one element out of y
such elements. But turns out it's not so [in fact it's the opposite(?) ]
The guides/tutorials seem hellbent on bring matrices to explain this which makes it specific to 2D arrays. I'm looking to understand a general array_name[w][x] ... [n]
syntax.
Note: fine, syntax is syntax, and this is how C defines it, okay. Then, is it true that array_name[w][x] ... [n]
is simply an array of w
elements each of which is array_name[x] ... [n]
? But even this is not entirely correct because int a[][3] = {1,2,3,4,5,6,7};
is valid even though the RHS contains a number of elements not divisible by 3.
Upvotes: 1
Views: 135
Reputation: 123468
The way to read a multidimensional array declaration like
int arr[N][M];
is as an N-element array of M-element arrays of int
. Each arr[i]
has type int [M]
.
We can get there using substitution. Let's start with a simple object declaration:
T a;
a
is an instance of something which we call T
. Now replace T
with the array type R [N]
:
R a[N];
Important thing to note - since the []
operator is postfix in both expressions and declarations, when we substitute T
with R [N]
the [N]
goes to the rightmost side of the declarator a
, giving us R a[N]
; the importance of this will be clear on the next round of substitution.
So now a
is an N-element array of something, and that something is type R
. Now we replace R
with another array type, int [M]
:
int a[N][M];
Again, since the []
operator is postfix, we need to add it to the rightmost side of the declarator a[N]
when doing the substitution, giving us a[N][M]
. a
is still an N-element array of something, it's just now that something is "M-element array of int
". Hence, a
is an N-element array of M-element arrays of int
.
But even this is not entirely correct because int a[][3] = {1,2,3,4,5,6,7}; is valid even though the RHS contains a number of elements not divisible by 3.
That's covered here:
6.7.9 InitializationC 2011 Online Draft
...
21 If there are fewer initializers in a brace-enclosed list than there are elements or members of an aggregate, or fewer characters in a string literal used to initialize an array of known size than there are elements in the array, the remainder of the aggregate shall be initialized implicitly the same as objects that have static storage duration.
So that initializer is interpreted as:
int a[][3] = {{1,2,3},{4,5,6},{7,0,0}};
Upvotes: 0
Reputation: 31389
int x[5][3];
declares x
as an array with 5 elements. Each of these elements is an array with 3 int
. You're correct so far.
But you should compile with -Wall -Wextra
. Look here:
k.c:2:16: warning: missing braces around initializer [-Wmissing-braces]
2 | int a[][3] = {1,2,3,4,5,6,7};
| ^
| { }{ }{}
It's valid to initialize it this way, but the more proper way of initializing it is:
int a[][3] = {{1,2,3},{4,5,6},{7,0,0}};
This is much more readable. The zeros are not needed. If you initialize one single element, all other elements will be zeroed.
One more thing is that you can go out of bounds without actually going out of bounds with multi dimensional arrays. DO NOTE THAT EVEN IF THIS IS LIKELY TO WORK, IT'S UNDEFINED BEHAVIOR, SO DON'T DO IT!
a[1][4] = (*a+1)[4]=*(*a+1)+4)
This is because []
is simply syntactic sugar for pointer arithmetic. So if you have declared T x[5][3];
for some type T
, then x[1][1]
will point to the same element as x[0][4]
But as I said, it's UB. Read more about it here
Upvotes: 6