First of all, sorry for my english if i make any grammar mistakes, etc ...
My question is, that when we have a two dimensional array, then if i am right, from the point of the computer and C/C++, it's just a long one dimensional array, the indices are just helping the compiler to map to the concrete address.
This code fragment works in Visual C++, however I would like to know, whether this code is portable and conforms to the standard (C++98), not causing surprises on other architectures and/or operating systems:
int arr[][3] = { 1, 5, 3, 7, 5, 2, 7, 8, 9 };
const int ARR_NUM = sizeof(arr) / sizeof(int);
int* ptr = reinterpret_cast<int*>(arr); // NOT: int(*)[][3] !!!
for (int i = 0; i < ARR_NUM; ++i) {
cout << ptr[i] << endl;
}
The data items in a multidimensional array are stored in the form of rows and columns. Also, the memory allocated for the multidimensional array is contiguous. So the elements in multidimensional arrays can be stored in linear storage using two methods i.e., row-major order or column-major order.
Memory is allocated contiguously when a two-dimensional array is declared as follows: int matrix [ 2 ][ 5 ] = {{ 1 , 2 , 3 , 4 , 5 },{ 6 , 7 , 8 , 9 , 10 }}; However, when we use a function such as malloc to create a two-dimensional array, there are variations in how memory can be allocated.
In C programming, you can create an array of arrays. These arrays are known as multidimensional arrays. For example, float x[3][4];
Because in physical memory, arrays are stored by column, such that all of column 1's contents reside consecutively then column 2's, column 3's, and so on. Such arrangement in memory is known as column major order. Not all programming languages will be column major order, some will be row major order.
The elements of the multidimensional array are stored sequentially in row-major order, so the manual indexing is portable:
C++98, 8.3.4/1:
An object of array type contains a contiguously allocated non-empty set of N sub-objects of type T.
Obviously for a multidimensional array this applies recursively.
However, this use of reinterpret_cast
is not portable. The standard says (C++98, 5.2.10/1) that
[...] otherwise, the result is an rvalue and the [...], array-to-pointer, [...] standard conversions are performed on the expression v.
In other words, passing arr
immediately triggers a decay of the array to a pointer to its first element. Then (C++98, 5.2.10/3) comes the catch-all
The mapping performed by
reinterpret_cast
is implementation-defined.
The rest of the section lists a number of exceptions to this, specifying casts that are always well-defined. Seeing as none of them applies here, the conclusion is that technically it's implementation-defined by default.
Theoretically speaking, this is not portable. Practically, as long as the architectures are the same (e.g. x86) I would certainly expect the cast to work reliably.
Fortunately you don't have to assume anything like that because as others have mentioned, something like int* ptr = arr[0]
does the same thing and is guaranteed portable.
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