Понимание содержания памяти союза - PullRequest
8 голосов
/ 04 марта 2010

Предположим, я определил объединение следующим образом:

#include <stdio.h>

int main() {
    union u {
        int i;
        float f;
    };
    union u tst;
    tst.f = 23.45;

    printf("%d\n", tst.i);

    return 0;
}

Может кто-нибудь сказать мне, как будет выглядеть память, в которой хранится tst?

Я пытаюсь понять вывод 1102813594, который производит эта программа.

Ответы [ 5 ]

11 голосов
/ 04 марта 2010

Это зависит от реализации (компилятор, ОС и т. Д.), Но вы можете использовать отладчик, чтобы увидеть содержимое памяти, если хотите.

Например, в моем MSVC 2008:

0x00415748  9a 99 bb 41

- содержимое памяти. Считайте из LSB слева (Intel, машина с прямым порядком байтов), это 0x41bb999a или действительно 1102813594.

Однако, как правило, целое число и число с плавающей запятой хранятся в одних и тех же байтах. В зависимости от того, как вы получаете доступ к объединению, вы получаете целое число или число с плавающей запятой интерпретация этих байтов. Размер пространства памяти, опять же, зависит от реализации, хотя обычно это самая большая из его составляющих, выровненных по некоторой фиксированной границе.

Почему ценность такая, какая она есть в вашем (или моем) случае? Вы должны прочитать о представлении чисел с плавающей точкой для этого (посмотрите ieee 754)

5 голосов
/ 04 марта 2010

Результат зависит от реализации компилятора, но для большинства компиляторов x86 float и int будут одинакового размера. В Википедии есть довольно хорошая схема расположения 32-битного числа с плавающей запятой http://en.wikipedia.org/wiki/Single_precision_floating-point_format,, которое может помочь объяснить 1102813594.

Если вы распечатаете int как шестнадцатеричное значение, это будет легче выяснить.

printf("%x\n", tst.i);
4 голосов
/ 04 марта 2010

При объединении обе переменные сохраняются, начиная с одной и той же ячейки памяти. Число с плавающей запятой хранится в формате IEEE (стандартный номер не запоминается, вы можете посмотреть его [править: как отмечают другие, IEEE 754]). Но это будет нормализованное дополнение к двум (у мантиссы всегда от 0 до 10, показатель степени может быть любым) с плавающей запятой.

вы берете первые 4 байта этого числа (опять же, вы можете посмотреть, какие биты идут в 16 или 32 битах, которые занимает поплавок, не помню). Так что это в основном ничего не значит, и это не полезно как int. То есть, если вы не знаете, почему вы хотите сделать что-то подобное, но обычно комбинирование с плавающей точкой и int не очень полезно.

И, нет, я не думаю, что это определяется реализацией. Я считаю, что стандарт определяет, в каком формате находится число с плавающей точкой.

3 голосов
/ 04 марта 2010

В союзе участники будут использовать одну и ту же память. так что мы можем получить значение с плавающей точкой как целочисленное значение.

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

Например: Если я храню 12 целое число в (32 бита). мы можем получить это значение 12 в формате с плавающей запятой.

Будет храниться со знаком (1 бит), экспонентой (8 бит) и значительной точностью (23 бита).

1 голос
/ 20 апреля 2013

Я написал небольшую программу, которая показывает, что происходит, когда вы сохраняете битовую комбинацию 32-разрядного числа с плавающей запятой в 32-разрядное целое число. Он дает вам точно такой же вывод, который вы испытываете:

#include <iostream>

int main()
{
    float f = 23.45;
    int x = *reinterpret_cast<int*>(&f);

    std::cout << x; // 1102813594
}
...