Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
231 views
in Technique[技术] by (71.8m points)

c - 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.

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

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. [...]


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...