Array pointer aliasing - undefined behavior?
Asked Answered
L

1

16

Does the following code invoke undefined behavior (due to aliasing violation or otherwise)?

int foo(int (*a)[10], int (*b)[5])
{
    (*a)[5]++;
    return (*b)[0];
}

int x[10];
foo(&x, (int (*)[5])&x[5]);

Note that the corresponding code using plain int * rather than pointer-to-array types would be perfectly legal, because a and b would be pointers to the same type and thus allowed to alias one another.

Edit: The interesting consequence, if this is in fact an aliasing violation, is that it seems to be a hackish but valid way to get restrict semantics pre-C99. As in:

void some_func(int *aa, int *bb)
{
    int (*a)[1] = (void *)aa;
    int (*b)[2] = (void *)bb;
    /* Now **a and **b can be assumed by the compiler not to alias */
}

Presumably if you needed to access an actual array at each address, you could use SIZE_MAX-1 and SIZE_MAX-2 etc. as the differing sizes.

Lab answered 15/8, 2011 at 4:39 Comment(1)
They're pointers to the same type, they cannot be assumed not to alias.Chuffy
M
6

You are not accessing objects through pointers of different type here: you are not manipulating the array objects to which a and b point themselves but the objects pointed to by (*a)+5 and (*b)+0, namely *((*a)+5) and *((*b)+0). Since these are pointers to the same type they may well alias to the same object.

The implicit assignment by the ++ operator is a valid assignment to the object pointed to by (*b)+0: ++ is equivalent to x = x + 1 (besides x being evaluated only once) and for simple assignment = the standard says

If the value being stored in an object is read from another object that overlaps in any way the storage of the first object, then the overlap shall be exact and the two objects shall have qualified or unqualified versions of a compatible type; otherwise, the behavior is undefined.

The types here are exactly the same and the overlap is exact.

Milky answered 15/8, 2011 at 9:9 Comment(3)
+1 Very interesting. Though, I still hate all this pointers semantics stuff…Shankle
By this logic, wouldn't accessing int[5][5] and an overlaid int[25] also be valid...?Lab
@R.. yes, I think it would be valid. Arrays are somehow in a grey zone. For a struct it is clear that accessing a field toto.x accesses the object as a whole, A[24] and B[4][4] are defined by pointer arithmetic and thus never access the array as a whole.Milky

© 2022 - 2024 — McMap. All rights reserved.