Как *i и u.i печатать разные номера в этом коде, хотя i определяется как int *i = &u.i;? Я могу только предположить, что я запускаю UB здесь, но я не понимаю, как именно.
(ideone demo реплицируется, если я выбираю "C" в качестве языка. Но, как указывал @2501, не "C99 strict" - это язык. снова, я получаю проблему с gcc-5.3.0 -std=c99!)
// gcc -fstrict-aliasing -std=c99 -O2
union
{
int i;
short s;
} u;
int * i = &u.i;
short * s = &u.s;
int main()
{
*i = 2;
*s = 100;
printf(" *i = %d\n", *i); // prints 2
printf("u.i = %d\n", u.i); // prints 100
return 0;
}
(gcc 5.3.0, с -fstrict-aliasing -std=c99 -O2, также с -std=c11)
Моя теория такова, что 100 является "правильным" ответом, потому что запись члену объединения через short -lvalue *s определяется как таковая (для этой платформы /endianness/whatever ). Но я думаю, что оптимизатор не понимает, что запись в *s может быть псевдоним u.i, и поэтому он считает, что *i=2; - единственная строка, которая может повлиять на *i. Это разумная теория?
Если *s может псевдоним u.i, а u.i может быть псевдоним *i, то, конечно, компилятор должен думать, что *s может псевдоним *i? Не следует ли переходить на псевдонимы "транзитивным"?
Наконец, у меня всегда было это предположение, что проблемы с жестким сглаживанием были вызваны плохим кастингом. Но в этом нет никакого каста!
(Мой фон - С++, я надеюсь, что задаю здесь разумный вопрос о C. Мое (ограниченное) понимание состоит в том, что на C99 допустимо писать через один член профсоюза, а затем читать через другого члена другого типа.)