Как *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 допустимо писать через один член профсоюза, а затем читать через другого члена другого типа.)