关于union的一些疑惑,求高手帮忙解惑

xinyilixun 2013-04-29 10:12:59

由一道题引入:

下面程序的输出结果为:

#program pack(8)
union A
{
char c[14];
int b;
};

int main(void)
{

printf("size: %d\n", sizeof(A));

return 0;
}

A. 4 B.16 C.12 D.14

答案是:B.16


为什么答案是16呢?我试着改为c[12],结果是12。
有int b情况下,改为c[13],c[14],c[15],c[16]结果都是16。 c[17]结果是20.
没有int b情况下,改为c[13],c[14],c[15],c[16],结果分别是13,14,15,16


求解释这种现象

下面为一些union的资料:

一直以来,union都是个很少用到的东西,对于这些不常用的结构往往记不住。这次看书又看到了,还是学习一下吧。
一般在Windows API的一些数据结构中才能看到这个union,其实并不复杂。本质上来说和结构体是一样的,但是从包装的角度来看有差异。
1、union中可以定义多个成员,union的大小由最大的成员的大小决定。
2、union成员共享同一块大小的内存,一次只能使用其中的一个成员。
3、对某一个成员赋值,会覆盖其他成员的值(也不奇怪,因为他们共享一块内存。但前提是成员所占字节数相同,当成员所占字节数不同时只会覆盖相应字节上的值,比如对char成员赋值就不会把整个int成员覆盖掉,因为char只占一个字节,而int占四个字节)
4、联合体union的存放顺序是所有成员都从低地址开始存放的。
下面看一个简单的代码:
#include <stdio.h>

typedef union{
char c;
int a;
int b;
}Demo;

int main(int argc, char **argv)
{
Demo d;
d.c = 'H';
d.a = 10;
d.b = 12;

printf("size: %d\n", sizeof(d));
printf("%c\t%d\t%d\n", d.c, d.a, d.b);

return 0;
}

//输出:
size:4




...全文
123 10 打赏 收藏 转发到动态 举报
写回复
用AI写文章
10 条回复
切换为时间正序
请发表友善的回复…
发表回复
小竹z 2013-04-30
  • 打赏
  • 举报
回复
union虽然按照最大成员分配内存,但是在分配内存时也要按照字节对齐机制。话说楼主虽然使用了#program pack(8),但是该联合体内实际最小分配单元为4个字节,所以会按照4字节对齐,char c[14]占14个字节,需要对齐到4字节的整数倍16字节。
lm_whales 2013-04-30
  • 打赏
  • 举报
回复
#program pack(8) 才是决定因素,8字节对齐 不够就补 14字节会补够16字节
Simeone_xu 2013-04-30
  • 打赏
  • 举报
回复
引用 8 楼 zhapin123 的回复:
#pragma pack(n)来设定变量以n字节对齐方式。n字节对齐就是说变量存放的起始地址的偏移量有两种情况:第一、如果n大于等于该变量所占用的字节数,那么偏移量必须满足默认的对齐方式,第二、如果n小于该变量的类型所占用的字节数,那么偏移量为n的倍数,不用满足默认的对齐方式。 有int b情况下,改为c[13],c[14],c[15],c[16]结果都是16。char c[]对齐方式是按1字节,int b对齐方式是4字节,以最大的作为联合体的对齐方式,所以结果是16。c[17]情况下也是如此。 没有int b情况下,改为c[13],c[14],c[15],c[16]。char c[]对齐方式是1字节,联合体最大对齐方式是1字节,因此是13,14,15,16
解释的很合理
沙尘暗影 2013-04-30
  • 打赏
  • 举报
回复
引用 7 楼 libralibra 的回复:
[quote=引用 2 楼 Athenacle_ 的回复:] sizeof是函数?。。牛人啊
承认我犯个错误,我一直当函数用的,没注意,也没搞明白这个运算符与函数到底有啥特殊区别. 不过是运算符还是函数,不是楼主问题的重点,重点是sizeof的时候的字节对齐问题 [/quote]这样体会运算符的函数的区别:函数有参数和返回值,但是sizeof可以这样用:size_t s = sizeof int;显然这不是函数的用法
zhapin123 2013-04-30
  • 打赏
  • 举报
回复
#pragma pack(n)来设定变量以n字节对齐方式。n字节对齐就是说变量存放的起始地址的偏移量有两种情况:第一、如果n大于等于该变量所占用的字节数,那么偏移量必须满足默认的对齐方式,第二、如果n小于该变量的类型所占用的字节数,那么偏移量为n的倍数,不用满足默认的对齐方式。 有int b情况下,改为c[13],c[14],c[15],c[16]结果都是16。char c[]对齐方式是按1字节,int b对齐方式是4字节,以最大的作为联合体的对齐方式,所以结果是16。c[17]情况下也是如此。 没有int b情况下,改为c[13],c[14],c[15],c[16]。char c[]对齐方式是1字节,联合体最大对齐方式是1字节,因此是13,14,15,16
libralibra 2013-04-30
  • 打赏
  • 举报
回复
引用 2 楼 Athenacle_ 的回复:
sizeof是函数?。。牛人啊
承认我犯个错误,我一直当函数用的,没注意,也没搞明白这个运算符与函数到底有啥特殊区别. 不过是运算符还是函数,不是楼主问题的重点,重点是sizeof的时候的字节对齐问题
怪人伽利略 2013-04-29
  • 打赏
  • 举报
回复
正解。。。。。。
anshiny 2013-04-29
  • 打赏
  • 举报
回复
引用 2 楼 Athenacle_ 的回复:
sizeof是函数?。。牛人啊
sizeof是运算符吧
Athenacle_ 2013-04-29
  • 打赏
  • 举报
回复
引用 1 楼 libralibra 的回复:
你这个问题光看union定义不行,还得看sizeof这个函数. When applied to a class type, the result is the size of an object of that class plus any additional padding required to place such object in an array. 如果你的union含有int,所以是4字节对齐,sizeof的返回值会向不小于"真实"size的最小的4的倍数对齐.也就是: 13,14,15,16 ==> 16 9,10,11,12 ==> 12 5,6,7,8 ==> 8 1,2,3,4 ==> 4 当你删除了int,你的union是1字节对齐的,这时候,你指定那个数组多长,sizeof返回值就是多少.
sizeof是函数?。。牛人啊
libralibra 2013-04-29
  • 打赏
  • 举报
回复
你这个问题光看union定义不行,还得看sizeof这个函数. When applied to a class type, the result is the size of an object of that class plus any additional padding required to place such object in an array. 如果你的union含有int,所以是4字节对齐,sizeof的返回值会向不小于"真实"size的最小的4的倍数对齐.也就是: 13,14,15,16 ==> 16 9,10,11,12 ==> 12 5,6,7,8 ==> 8 1,2,3,4 ==> 4 当你删除了int,你的union是1字节对齐的,这时候,你指定那个数组多长,sizeof返回值就是多少.

64,647

社区成员

发帖
与我相关
我的任务
社区描述
C++ 语言相关问题讨论,技术干货分享,前沿动态等
c++ 技术论坛(原bbs)
社区管理员
  • C++ 语言社区
  • encoderlee
  • paschen
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
  1. 请不要发布与C++技术无关的贴子
  2. 请不要发布与技术无关的招聘、广告的帖子
  3. 请尽可能的描述清楚你的问题,如果涉及到代码请尽可能的格式化一下

试试用AI创作助手写篇文章吧