Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Array pointer aliasing - undefined behavior?

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.

like image 992
R.. GitHub STOP HELPING ICE Avatar asked Aug 15 '11 04:08

R.. GitHub STOP HELPING ICE


People also ask

What is the problem of aliasing while using pointers?

Two seemingly different pointers may point to storage locations in the same array (aliasing). As a result, data dependencies can arise when performing loop-based computations using pointers, as the pointers may potentially point to overlapping regions in memory.

What is the strict aliasing rule?

"Strict aliasing is an assumption, made by the C (or C++) compiler, that dereferencing pointers to objects of different types will never refer to the same memory location (i.e. alias each other.)"

Does C++ have strict aliasing?

In both C and C++ the standard specifies which expression types are allowed to alias which types. The compiler and optimizer are allowed to assume we follow the aliasing rules strictly, hence the term strict aliasing rule.

What is C++ aliasing?

In C, C++, and some other programming languages, the term aliasing refers to a situation where two different expressions or symbols refer to the same object.


1 Answers

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.

like image 125
Jens Gustedt Avatar answered Sep 29 '22 16:09

Jens Gustedt