Why in C/C++ it is needed for a func param that receives a MD arr to has the sizes of all sub arrays/dimensions?
here(PDF): It says the only difference of MD arrs is that "the compiler remembers each imaginary dimension" but when I violate these dimensions compiler does nothing, e.g.:
char arr[3][5];
arr[0][5] = 10;
So, what's the point of remembering those sizes?
Indexed access into an array must compute memory offset calculations in row-major order based on the index value and declared inferior dimensions. More on that in a bit.
But first, your question is tightly related to this simple observation:
void foo( char a[] )
{
a[5] = 'a';
}
// caller of foo() from somewhere
char arr[5];
foo(arr);
Why does the compiler let you do that ?? Because this is C, and you're perfectly within your rights to shoot your own foot off with undefined behavior. Keeping this in mind:
void foo( char a[][5] )
{
a[0][5] = 'a';
}
// caller of foo() from somewhere
char arr[4][5];
foo(arr);
It is just as "valid" as the prior code (i.e. you're well within your right to enter into UB at your own risk and peril). In this case it will "work", but only because the linear backdrop of the underlying array is twenty elements wide, and we're only accessing the sixth element, which is technically arr[1][0]
.
The purpose of those inferior dimensions is to properly calculate access like this:
void foo( char a[][5] )
{
a[2][1] = 'b';
}
The 2
superior index must use the declared inferior dimension (in this case 5
) to effectively calculate the the linear offset of the proper element. Laying out the 2D array in a 1D linear block, it is used to do this:
char arr[20]; // 4*5
arr[2*5+1] = 'b';
Note the 5
. It, the declared inferior dimension, must be known to properly calculate the row-leap (figure of speech).
I hope that makes it at least a little clearer.
I should note that this compounds. I.e., the following:
char arr[3][4][5];
arr[1][2][3] = 'c';
effectively computes the correct location against the linear backdrop of the underlying array:
char arr[60]; // 3*4*5
arr[ 1*(4*5) + 2*(5) + 3 ] = 'c';
And so on. Take that out to as many dimensions as you desire. All the inferior dimensions must be known to do this properly.
An array is not a special kind of object, it's just a long list of items. Your arr[3][5]
is in fact just an arr[15]
and the arr[0][5]
is then redirected to arr[5]
by the compiler.
Because C/C++ don't store the sizes, you need to hardcode them to make the [0][5]
map to [5]
correctly.
Some compilers might enforce the [0][5]
to be wrong (or warn about it), but since it maps to [5]
, it'll do at least something.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With