Стандарт C99 (§6.7.2.1.14) говорит:
Размер союза является достаточным, чтобы содержать самый большой из его членов. Значение в в любой момент может быть сохранено в одном объекте. Указатель на объект объединения , соответствующим образом преобразованный, указывает на каждый из его членов (или если элемент представляет собой бит- , а затем в блок, в котором он находится) и наоборот.
(курсив добавлен)
Смелое заявление на самом деле говорит, что каждый член союза имеет тот же адрес, так что все они «начинают» по тому же адресу. t
, как t.ch
как t.i
, должен быть по адресу 2000, таким образом t.ch
перекрывается с первым байтом (в адресном порядке) t.i
.
Что это означает, что с точки зрения «что я могу получить, если я пытаюсь прочитать t.i
после установки t.c
» в реальном мире зависит от платформы байтов, а в фактах, пытаясь прочитать член союза, когда вы писали в другой одно - это неспецифическое поведение в соответствии со стандартом C (§6.2.6.1.6/7, переформулированное в §J.1.1).
Что помогает больше понять порядок байтов машины (по крайней мере, я думаю, что это проще понять), чтобы иметь союз, как это:
union
{
int i;
unsigned char ch[sizeof(i)];
} t;
делает
t.i=20;
, а затем посмотрев, что находится внутри двух символов в t.ch
. Если вы находитесь на маленькой машине, вы получите t.ch[0]==20
и t.ch[1]==0
, а наоборот, если вы на большой машине (если sizeof(int)==2
). Обратите внимание, что, как уже говорилось, это специфическая для реализации детальность, стандарт даже не упоминает о контенте.
Чтобы сделать его еще понятнее: если у вас есть 2-байтовый int
var, установленный на 20, на машинке с маленькими деталями, сбрасывая связанную с ним память в адресном порядке, вы получите (в шестнадцатеричном представлении, байты разделены пробелом):
14 00
в то время как на большой Endian машине вы получите
00 14
большой обратный порядок байт представление выглядит «более правильный» с нашей точки зрения, потому что в маленькое конечное представление байтов, которые составляют целое int
хранятся в обратном порядке.
Кроме того, я хочу сказать, что если я делаю это:
int a=20;
printf("%d",* (char*)&a);
Тогда не выход зависит от порядок байтов т.е. ли 20 хранится в 2000 или 2001 ?
Да, вот оно, но в вашем вопросе вы спрашиваете другое; это выглядит больше мой пример.
Я не уверен, что endian-ness имеет какое-либо отношение к тому, где хранится объединение ... не все ли типы объединения хранятся в одном и том же месте (т. Е. При смещении нуля)? (Хороший вопрос, хотя!) –
2001 маловероятно, так как неравномерный доступ к памяти либо медленный, либо запрещенный в зависимости от архитектуры. –
@Platinum Azure: если мы просто определим int a = 20; то разве это не зависит от того, где 20 хранится? –