Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Cast T[][] to T*

Is it safe to cast a 2D array of type T to T* and dereference the elements?

Since the memory layout of 2D array is linear the base pointer should be equal to pointer to the first element. Since the final type they are pointing to is also the same, there shouldn't be any alignment difference issue.

Or there is some aspect that can cause Undefined Behaviour?

Just to be clear I mean something like this -

int arr[10][10];
int p = *((int*) arr);

Also, the same question if I access elements beyond the first array i.e. (int*) arr + 13. Would it come under the clause of out of bounds access? Since I am accessing outside the bounds of the first array.

like image 827
Ajay Brahmakshatriya Avatar asked May 08 '17 15:05

Ajay Brahmakshatriya


1 Answers

The cast itself is fine. What might indeed be questionable would be using a pointer to an element within one subarray to access elements in a different one: While the operation is clearly well-defined at a lower level (everything's aligned properly, no padding, the types match, ...), my impression of the C standard has been that it is worded in a way that allows bounds-checking implementations to be standards-conforming.

Note, however, that linearly traversing a multi-dimensional array might nevertheless still be permissible as a pointer pointing past a subarray (which normally must not be dereferenced) also happens to be a pointer to the first element of the next subarray. What this thought leads to is pointer arithmetics being non-associative:

It is my understanding that an expression such as (int *)arr + 13 involves undefined behaviour1, but might become well-defined if you split it into two steps ((int *)arr + 10) + 3.

If you do want to do it in a single step, there's of course also the option of dropping to the byte level, ie (int *)((char *)arr + 13 * sizeof (int)), which should be unproblematic as in contrast to other pointer types, character pointers are bounded by the outermost enclosing object.

I've had discussions about this before, but I don't remember if there ever was a definitive conclusion resolving this particular ambiguity.


1 C11, section 6.5.6 §8

[...] If both the pointer operand and the result point to elements of the same array object, or one past the last element of the array object, the evaluation shall not produce an overflow; otherwise, the behavior is undefined. [...]

like image 143
Christoph Avatar answered Oct 16 '22 20:10

Christoph