Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is this C++ code portable? (assuming multidimensional arrays have continuous memory layout)

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;
}
like image 712
Benj Avatar asked May 16 '12 12:05

Benj


People also ask

How are multidimensional arrays stored in memory in C?

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.

Are 2D arrays contiguous in memory?

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.

Does C allow multi dimensional arrays?

In C programming, you can create an array of arrays. These arrays are known as multidimensional arrays. For example, float x[3][4];

How 3d array is stored in memory?

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.


1 Answers

Standardese

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.

Final conclusion

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.

like image 148
Jon Avatar answered Oct 27 '22 01:10

Jon