This question may be a bit controversial. I have a following code at block scope:
int *a = malloc(3 * sizeof(int));
if (!a) { ... error handling ... }
a[0] = 0;
a[1] = 1;
a[2] = 2;
I argue that this code invokes UB due to pointer arithmetics outside of bounds.
The reason is that the effective type of the object pointer by a
is never
set to int[3]
but rather int
only. Therefore any access to the object at an index
other than 0 is not defined by C standard.
Here is why:
Line a = malloc(...)
.
If the allocation succeeds thena
points for a region large enough to store 3 int
s.
a[0] = ...
is equivalent to *a = ...
, an l-value of int
. It sets the effective type of the first sizeof(int)
bytes to int
as indicated in the rule 6.5p6.
... For all other accesses to an object having no declared type, the effective type of the object is simply the type of the lvalue used for the access.
Now the pointer a
points to an object of type int
, not int[3]
.
a[1] = ...
is equivalent to *(a + 1) =
. Expression a + 1
points to an element one after the end of int
object accessible through *a
.
This pointer itself is valid for comparison but accessing is undefined due to:
Rule 6.5.6p7:
... a pointer to an object that is not an element of an array behaves the same as a pointer to the first element of an array of length one with the type of the object as its element type.
And rule 6.5.6p8:
... If the result points one past the last element of the array object, it shall not be used as the operand of a unary * operator that is evaluated.
The similar issue is relevant for a[2] = ...
but here even a + 2
hidden in a[2]
invokes UB.
The issue could be resolved if the standard allowed arbitrary pointer arithmetic with the valid region of memory as long as alignment requirements and strict aliasing rule is satisfied. Or that any collection of the consecutive objects of the same type can be treated as an array. However, I was not able to find such a thing.
If my interpretation of the standard is correct then some C code (all of it?) would be undefined. Therefore it is one of those rare cases when I hope that I am wrong.
Am I?