Подтвердить что ты не робот

Алиасирование указателя массива - поведение undefined?

Вызывает ли следующий код поведение undefined (из-за нарушения псевдонимов или иначе)?

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

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

Обратите внимание, что соответствующий код с использованием plain int *, а не типа указателя на массив, будет совершенно легальным, потому что a и b будут указателями на один и тот же тип и, таким образом, будут иметь псевдоним друг друга.

Изменить: Интересное следствие, если это на самом деле является нарушением псевдонимов, заключается в том, что он кажется хакерским, но действительным способом получения семантики restrict pre-C99. Как в:

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 */
}

Предположительно, если вам нужно получить доступ к фактическому массиву по каждому адресу, вы можете использовать SIZE_MAX-1 и SIZE_MAX-2 и т.д. как разные размеры.

4b9b3361

Ответ 1

Здесь вы не получаете доступа к объектам с помощью указателей различного типа: вы не манипулируете объектами массива, к которым указывают a и b, но объекты, на которые указывают (*a)+5 и (*b)+0, а именно *((*a)+5) и *((*b)+0). Так как это указатели на один и тот же тип, они могут быть похожими на один и тот же объект.

Неявное присвоение оператором ++ является допустимым назначением объекту, на который указывает (*b)+0: ++ эквивалентно x = x + 1 (кроме того, x оценивается только один раз) и для простого назначения = стандарт говорит

Если значение, хранящееся в объекте, считывается с другого объекта который каким-либо образом перекрывает хранение первого объекта, затем наложение должно быть точным, и оба объекта должны иметь неквалифицированные версии совместимого типа; в противном случае поведение      undefined.

Типы здесь точно такие же, и перекрытие является точным.