Если вы используете
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
покрывает больше байтов.