联合的内存分配

时间:2018-02-12 17:06:30

标签: c unions

在以下代码中

const
  AFilename = '/tmp/folders/bla.txt';
begin
  if NOT FileExists(AFilename) then begin
    if NOT DirectoryExists(ExtractFilePath(AFilename)) then
      if NOT ForceDirectories(ExtractFilePath(AFilename)) then RaiseLastOSError;
    if (FileCreate(AFilename) = INVALID_HANDLE_VALUE) then RaiseLastOSError;
  end;

我得到的输出是

#include <stdio.h>

int main() {
    union a {
        int i;
        char ch[2];
    };
    union a u;
    int b;
    u.ch[0] = 3;
    u.ch[1] = 2;
    printf("%d,%d,%d\n", u.ch[0], u.ch[1], u.i);
    return 0;
}

任何人都可以解释为什么3,2,515 的价值是i吗?

2 个答案:

答案 0 :(得分:4)

union a {
        int i;
        char ch[2];
};
union a u; /* initially it contains gargage data */

联盟的所有成员共享公共记忆。在上面的情况下,为u分配了总共4个字节,因为在4个字节(需要MAX内存)中,您可以存储ich

                        ch[1]    ch[0]
    ----------------------------------
   |     G  |   G    |   G   |  G    |  => G means garbage/junk data, because u didn't initialized 
    ----------------------------------
                                     u
  MSB                               LSB

当语句u.ch[0] = 3;仅执行ch[0]初始化时。

                  ch[1]    ch[0]
    --------------------------------------
   |     G  |   G    |   G   | 0000 0011 |  => G means garbage/junk data, because u didn't initialized 
    --------------------------------------
                                        u
 MSB                                   LSB

u.ch[1] = 2;接下来执行时,1个字节被初始化为

                        ch[1]       ch[0]
    ------------------------------------------
   |     G  |   G    | 0000 0010  | 0000 0011 |  => G means garbage/junk data, because u didn't initialized 
    ------------------------------------------
                                              u
 MSB                                        LSB

正如您在上面看到的4 bytes只有前2个字节得到已初始化,仍然剩下的2个字节未初始化,因此当您打印{{1 },未定义的行为

如果你想要预期的结果,那么先将union变量初始化为

u.i

现在当你打印union a u = { 0 }; /* all 4 bytes got initialized at first instance itself, no chance of any junk data */ u.ch[0] = 3; u.ch[1] = 2; 时,它会打印整个4字节的数据u.i(如果是小的enidian处理器)

答案 1 :(得分:0)

你的工会变量的大小&#39; u&#39;是4个字节(32位机器)。 假设您有工会变量的起始地址&#39; u&#39;如2000年。

现在,3存储在2000(ch [0])中,2存储在2001(ch [1])中。 内存位置2000的二进制值为00000011(十进制为3),内存位置2001的二进制值为00000010(十进制为2)。

现在,当您尝试打印&#39; u.i&#39;时,两个char变量的值&#39; ch [0]&#39;和&#39; ch [1]&#39;组合在一起形成一个16位的整数,其值为0000001000000011(十进制为515)。这就是为什么你得到整数变量&#39; u.i&#39;的值515。您的机器遵循little-endian格式对内存中的字节进行排序。如果您的机器是一个大端机器,那么您可能已经得到了“u.i&#39;如770而不是515.