C中联合的内存分配

时间:2017-11-16 17:00:13

标签: c arrays unions

我最近正在学习工会,即使在阅读了很多相关内容之后也会感到困惑。

#include<stdio.h> 
union test
{
    int x;
    char arr[4];
    int y;
};

int main()
{
    union test t;
    t.x = 0;
    t.arr[1] = 'G';
    printf("%s\n", t.arr);
    printf("%d\n",t.x);
    return 0;
}

我的理解是:

由于xarr[4]共享相同的内存,因此当我们设置x = 0时,arr的所有字符都设置为00'\0'的ASCII值。当我们执行&#34; t.arr[1] = 'G'&#34;时,arr[]变为&#34; \0G\0\0&#34;。当我们使用"%s"打印字符串时,printf函数从第一个字符开始并保持打印直到找到\0。由于第一个字符本身为\0,因此不会打印任何内容。

我没有得到的是第二份printf声明

现在arr[]是&#34; \0G\0\0&#34; ,xy共享相同的位置。 所以我认为x是以下

00000000 01000111 00000000 00000000(&#34; \0G\0\0&#34;)

所以t.x应该打印4653056。 但它的打印是18176

我哪里错了?

这在技术上是不确定的还是由于一些愚蠢的错误或者我错过了一些概念?

2 个答案:

答案 0 :(得分:8)

Union的所有成员将分享same common memory。假设union的起始地址是0x100。 当你写t.x = 0;时,整个4个字节的初始化为零,为

-------------------------------------------------
| 0000 0000 | 0000 0000 | 0000 0000 | 0000 0000  |
-------------------------------------------------
0x104     0x103       0x102        0x101        0x100
                                                 x,arr,y 

当你写作t.arr[1] = 'G';时,arr [1]将覆盖&#39; G&#39; ascii值,看起来像

-------------------------------------------------
| 0000 0000 | 0000 0000 | 0100 0111 | 0000 0000  |
-------------------------------------------------
0x104     0x103       0x102        0x101        0x100 

现在计算这个值为18176。

答案 1 :(得分:1)

tl; dr:endianity!

当printf从你的工会指向的内存中读取数据时,它会查看系统的字节顺序并读取存储在little endian中的数据。 因此,不是打印存储在内存中的数据(0x00470000),而是获得数字0x00004700,这与18176相关,就像你得到的那样。

代码示例:

#include<stdio.h> 
union test
{
    int x;
    char arr[4];
    int y;
};

int main()
{
    union test t;
    t.x = 0;
    t.arr[1] = 'G';
    printf("%s\n", t.arr);
    printf("%d\n",t.x); // prints 18176

    t.x = 0;
    t.arr[2] = 'G';
    printf("%d\n",t.x); // prints 4653056
    return 0;
}

或者在Python中:

import struct

union_data = "\x00G\x00\x00"
print struct.unpack("<I", a)[0] # This is little endian. Prints 18176
print struct.nupack(">I", a)[0] # This is big endian. Prints 4653056

奖金!您还可以使用函数htonl将读取为小端的整数转换为大端。 See more at the docs