Вывод объединения с использованием оператора if - PullRequest
1 голос
/ 13 июня 2019

Эй, у меня проблема с домашним заданием в этом коде c:

#include<stdio.h>

typedef union{
    char var1;
    int var2;
    float var3;
}data;

int main()
{
    data mydata;

    mydata.var1 = 'B';
    mydata.var2 = 12;

    if(mydata.var1 == 'B')
        mydata.var3 = 3.5;
    else
        mydata.var3 = 7.1;

    printf("%.1f", mydata.var3);
    return 0;
}

Вывод равен 7.1, мне было интересно, кто-нибудь может объяснить, почему вывод равен 7.1, а не 3.5.

Приветствую вас за помощь.

Ответы [ 2 ]

5 голосов
/ 13 июня 2019

Первое, что вы должны знать, - это то, что union выделяет одно общее пространство хранения для всех своих членов. Мы можем получить доступ только к одному члену профсоюза одновременно.

В вашем примере «B» назначен члену профсоюза «mydata.var1». Имя ячейки памяти - mydata.var1, а значение, хранящееся в этой ячейке, - «B». Затем 12 назначается члену профсоюза "mydata.var2". Теперь имя ячейки памяти - «mydata.var2» со значением 12. (Союз может содержать только одного члена одновременно). По этой причине ваша другая часть вызывается в вашей программе. Если вы хотите напечатать 3.5 вместо 7.1, тогда вы должны использовать struct вместо union, потому что структура выделяет пространство для всех членов отдельно.

typedef struct{
    char var1;
    int var2;
    float var3;
}data;

int main()
{
    data mydata;

    mydata.var1 = 'B';
    mydata.var2 = 12;

    if(mydata.var1 == 'B')
        mydata.var3 = 3.5;
    else
        mydata.var3 = 7.1;

    printf("%.1f", mydata.var3);
    return 0;
}

Надеюсь, это поможет вам.

0 голосов
/ 14 июня 2019

Вывод равен 7.1, мне было интересно, кто-нибудь может объяснить, почему вывод равен 7.1, а не 3.5.

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

С этой строкой:

mydata.var1 = 'B'; 

Вы устанавливаете значение этой памяти равным 0x42, а затем следующей строкой:

mydata.var2 = 12;

Вы устанавливаете значениеиз этой памяти до 12, так что, когда вы получите здесь:

if(mydata.var1 == 'B')
    mydata.var3 = 3.5;
else
    mydata.var3 = 7.1;

Предложение else выполняется, и теперь значение этой памяти установлено в 7.1.

Вотбольшая проблема с вашим кодом: использование объединения между char, int и float не имеет смысла

Причина относительно проста: объем памяти, необходимый для членов,разные.

Объем памяти, необходимый для char, составляет 1 байт, так как это наименьшая адресуемая единица для машины, на которой выполняется код.Объем памяти, необходимый для int (он же со знаком int), составляет по крайней мере 2 байта или 16 бит, но в настоящее время на большинстве компьютеров это 4 байта или 32 бита.Память, необходимая для float на большинстве машин, составляет 4 байта или 32 бита из-за двоичного формата с плавающей запятой IEEE 754 с одинарной точностью.Значения, которые могут представлять сами члены, также совершенно разные.Подписанное char обычно [-128, 127].int со знаком, предполагая 32 бита, составляет [-2217483,647, +2,147,483,647], а float равно [1,2 * 10 ^ -38, 3,4 * 10 ^ 38].Однако, по крайней мере, float и int, вероятно, будут иметь одинаковый размер, так что union, содержащий их, имеет больше смысла.

Я понимаю, что это, вероятно, образовательное или начинающее упражнение, однако этоупражнение, в котором не удалось выделить цель union и правильное ее использование.

Способ использования union состоит в том, чтобы интерпретировать одни и те же данные по-разному.

Типичным примером является то, сколько сетевых API будет определять объединение для адресов IPv4

union ipv4addr {
  unsigned  address;
  char      octets[4];
};

Это обеспечивает гибкость при передаче этой информации функции.Возможно, определенная функция заботится только о 32-битном значении, а другая - только о конкретных байтах в этом 32-битном значении.

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

...