Дает вывод: 65
A
Нет, не обязательно, потому что код вызывает неопределенное поведение, поскольку u1
не инициализируется и не ' Если его адрес занят, см. (Почему) использует неинициализированную переменную с неопределенным поведением?
Неопределенное поведение = не известно, что произойдет. В 32-разрядной системе с прямым порядком байтов в лучшем случае она печатает 3 байта неопределенного мусора, за которым следует 4-й байт со значением ASCII. Я получаю немного мусора 2005012545
. Чтобы разобраться с мусором, я мог бы вместо этого напечатать его в шестнадцатеричном виде: 0x77821041
, где 41
- младший бит, содержащий значение ASCII 0x41 / 65.
Это потому, что вы не инициализировали union
и затем вы, вероятно, запускаете отладочную сборку, которая просто обнуляет все значения стека, так что программа, кажется, работает для вас.
Исправьте это, инициализируя объединение известным значением: ... } u1 = {0};
.
Что касается u1.theChar = "A";
, он даже не компилируется на правильно настроенном компиляторе C (см. «Указатель из целого числа / целое число из указателя без преобразования») вопросы ). Поскольку строковый литерал "A"
в конечном итоге становится типом char*
при назначении. но theChar
имеет тип char
. Это также неопределенное поведение, которое бессмысленно понимать. В лучшем случае вы получите один из байтов из адреса указателя символов, хранящегося в theChar
, но код недействителен, поэтому нет никаких сведений о том, что он будет делать.
Необходимо исправления:
#include <stdio.h>
int main (void)
{
union {
int theInt;
char theChar;
} u1 = {0};
u1.theChar = 'A';
printf("%d\n", u1.theInt);
printf("%c\n\n", u1.theChar);
u1.theChar = "A"[0];
printf("%d\n", u1.theInt);
printf("%c\n\n", u1.theChar);
}
Вывод теперь предсказуем, пока мы придерживаемся систем с прямым порядком байтов:
65
A
65
A
32-битная система с большим порядком байтов должна вместо этого выводить:
1090519040
A
1090519040
A
1090519040 = 0x41000000