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

Как хранятся члены профсоюза?

union test
{
 int i;
 char ch;
}t;
int main()
{
 t.ch=20;
}

Предположим sizeof(int)==2, и адреса памяти, выделенные для t, - 2000, 2001.
Тогда где 20 i.e. t.ch хранится - в 2000 или 2001 году или зависит от конечности машины?

4b9b3361

Ответ 1

В стандарте C99 (§6.7.2.1.14) говорится:

Размер объединения достаточен, чтобы содержать самый большой из его членов. Значение at  большинство из них могут быть сохранены в объединенном объекте в любое время. Указатель на объединенный объект, соответствующим образом преобразованный, указывает на каждый из его членов (или если член является бит- поле, затем в блок, в котором он находится) и наоборот.

(выделено курсивом)

Смелое утверждение на самом деле говорит о том, что каждый член союза имеет один и тот же адрес, поэтому все они "начинаются" по одному и тому же адресу. t, как t.ch как t.i, должен находиться в адресе 2000, поэтому t.ch перекрывается с первым байтом (в адресном порядке) t.i.

Что это означает в терминах "что я получу, если попытаюсь прочитать t.i после установки t.c" в реальном мире, зависит от конечности платформы и в фактах, пытающихся прочитать член союза, когда вы в другом - это неспецифицированное поведение в соответствии со стандартом C (§6.2.6.1.6/7, переформулированное в § 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, на машине little-endian, сбросив связанную с ним память в адресном порядке, вы получите (в шестнадцатеричном представлении, байты, разделенные пробелом):

14 00

пока на большой машине вы получите

00 14

Представление с большой буквы выглядит "более правильным" с нашей точки зрения, потому что в маленьком концевом представлении байты, которые составляют все int, хранятся в обратном порядке.


Кроме того, я говорю, что если я это сделаю:

int a=20;
printf("%d",* (char*)&a);

Тогда не зависит результат от конечности, то есть, 20 хранится ли в 2000 или 2001 году?

Да, вот оно, но в вашем вопросе вы спрашиваете другую вещь; это больше похоже на мой пример.

Ответ 2

test будет принимать два байта и поэтому будет выделен по адресу 2000, 2002 и т.д. И любое значение для каждого экземпляра объединения будет сохранено, начиная с этого базового адреса.

Каждый член союза будет храниться по тому же адресу для этого экземпляра объединения. Поэтому вы можете хранить только один тип значения в объединении одновременно. Следовательно, объединения занимают количество байтов, необходимых для самого большого члена.