Как использовать Союз на языке Си - PullRequest
4 голосов
/ 30 апреля 2011

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

union student {
   int i;
   int j;
}x;

как мы можем получить доступ к i и j?если у нас есть: xi = 1;и тогда мы printf("%d",j); что будет?ошибка компилятора?Хорошо, тогда как насчет следующего случая:

union student {
       int i;
       float j;
    }x;

, если мы назначим xi = 2;каково значение xj?

Ответы [ 3 ]

12 голосов
/ 30 апреля 2011

Если вы используете

printf("%d", x.j); 

Вы увидите то же значение, которое вы присвоили x.i, поскольку обе переменные занимают одну и ту же область памяти. Не было бы типично делать обе переменные одного типа, как вы сделали. Обычно вы делаете это так, чтобы вы могли просматривать одни и те же данные, но с разными типами данных.

Представьте себе, например, что вы хотите трактовать double как double и время от времени напрямую обращаться к битам (1 и 0), которые представляют двойное число, вы сделали бы это со следующим объединением.

union DoubleData
{
    double d;
    char b[8];
} x;

Теперь вы можете присваивать / получать доступ к двойному элементу напрямую через член d или манипулировать тем же значением через 8 байтов, которые представляют двойное число в памяти.

Используя ваше последнее обновление вопроса,

union student 
{       
  int i;
  float j;    
}x;

Давайте сделаем предположение о вашей платформе, int - это 4 байта, а float - это 4 байта. В этом случае при доступе к x.j вы будете манипулировать и обрабатывать 4 байта как двойной, а при доступе к x.i вы будете манипулировать и рассматривать 4 байта как целое число.

Таким образом, обе переменные перекрываются в одной и той же области памяти, но что будет отличаться, так это то, как вы интерпретируете битовую комбинацию в этой области памяти. Имейте в виду, что любой 4-байтовый битовый шаблон является допустимым целым числом, НО не любой 4-байтовый битовый шаблон является допустимым значением с плавающей запятой.

Давайте сделаем еще одно предположение о вашей платформе: int - 2 байта, а число с плавающей запятой - 4 байта. В этом случае, когда вы получаете доступ к x.i, вы будете манипулировать только половиной битовой комбинации, которая перекрывается плавающей точкой, потому что x.i в этом случае будет только частично перекрывать x.j, поскольку x.j покрывает больше байтов.

1 голос
/ 30 апреля 2011

Это "неопределенное поведение".

Вы не можете писать в i, а затем читать из j. Вы можете одновременно использовать только один из элементов.

1 голос
/ 30 апреля 2011

Оба i и j будут совместно использовать одну и ту же память, поэтому все, что вы назначите одному, будет доступно и для другого участника.

x.i  = 1;
// x.j = 1
...