首页 > 试题广场 >

设有以下说明和定义: typedef union {

[填空题]
在32位机器上
设有以下说明和定义:
typedef union {
    long i; 
    int k[5]; 
    char c;
} DATE;
struct data { 
    int cat; 
    DATE cow; 
    double dog;
} too;
DATE max;
则语句 printf("%d",sizeof(struct data)+sizeof(max));的执行结果是:1
推荐
    这道题可能很多同学都有误区,不明白内存对齐的真正含义,那么下面我来讲解一下,首先共用体里面你们肯定都是明白的,DATE是一个union, 变量公用空间. 里面最大的变量类型是int[5], 占用20个字节. 所以它的大小是20 。
但是到了结构体里面,其实它是这样的,首先一个Int,然后后面5个int,再然后是一个double,所以最大的成员长度是8不是20,然后6个int刚刚24,然后加上8是32,加上共用体是52,如果你把第一个Int cat去掉,你仍然会发现,结构体大小还是32,因为8个字节内存对齐,前面2个int一组,最后还单一个int也要占8个字节。希望能对内存对齐不明白的童鞋有所帮助。
编辑于 2015-07-30 23:58:08 回复(28)
时间不多,同学们可以参考一下前面同学的回答,然后我再给出两个图相对应于楼上sunburtsRun同学说的有关struct的内存对齐问题。
这就是因为struct中有double类型,所有内存对齐没八位分配一块内存,然后内存对齐,因为,struct中内容顺序为1,int cat,2,Date cow(相当于5个int类型元素)3.一个double,所以内存图示如下:

那如果Date cow中是4个int是strcut占多少位内存呢?这还是与strcut内容中的顺序有关,大家看图下:这样可以大概明白什么是内存对齐了吧。
哈哈

发表于 2016-08-08 10:09:00 回复(0)
解该题的关键是
结构体变量的所有成员占用不同的存储空间,而共用体中所有成员只占用相同的内存单元,在任一时刻只有一个成员起作用
发表于 2015-09-04 21:17:26 回复(1)
sizeof(max))=20 因为max是联合体定义,而联合体内数据成员是共享内存空间,且每次只能使用一种数据类型,所以联合体的长度取决于联合变量中最长的元素,即 int k[5] 占20个字节
sizeof(struct data) 结构体为每个数据类型分配空间,可以同时使用多种类型, 结构体的总大小,必须是内部最大成员的整数倍;结构体中最长的是double=8个字节,考虑内存对齐原则,int 和联合体占据24个字节,所以 sizeof(struct data)=32
发表于 2016-08-04 21:18:11 回复(0)
对于union,分两步:先算union对齐大小,对齐的大小是取决于union成员中字节对齐最大的那个;再算union实际分配的空间,而分配给union的实际大小不仅要满足是对齐大小的整数倍,同时要满足实际大小不能小于最大成员的大小。DATE中,对齐大小是成员中字节对齐最大的那个,所以对齐大小为4,分配的实际大小既要满足是对齐大小的整数倍,又不能小于最大成员大小,最大成员是int k[5],所以实际分配的大小是20。
然后结构体data中,int cat 的对齐参数是4,偏移量为0,所以分配4个单位;DATE cow对齐参数是4,偏移量是4,可以整除,则分配20单位的长度;double dog的对齐参数是8,偏移量为24,可以整除,则直接分配8个单位的长度。最后data中分配长度是4+20+8=32.
最后20+32=52.
编辑于 2016-10-08 17:02:06 回复(1)
验证之后是60,最后的struct data要考虑对其吧,sizeof(struct data)应该为40。结构体的大小是结构体内最大成员大小的整数倍。
发表于 2015-07-02 17:22:21 回复(4)
typedef union {
    long i;
    int k[5];
    char c;
} DATE;
struct data {
    int cat;
    DATE cow;
    double dog;
} too;
DATE max;     
内存对齐原则:偏移量=min(pragma pack(),当前数据的长度)的倍数
union 在struct 内是当做连续 5 个 int 变量来处理
相当于:
typedef union {
    long i;
    int k[5];
    char c;
} DATE;
struct data {
    int cat;
    int k_0;
    int k_1;
    int k_2;
    int k_3;
    int k_4;
    double dog;
} too;
DATE max;
  所以,按照内存对齐原则:
  sizeof(too)=4+4+4+4+4+4 + 8 =32 因为前面6个int 后的偏移量 
 为24 是 sizeof(double) 的倍数,所以已经对齐
如果union 内的 int k[5] 变为 int k[4]
那么结果将变为 48 (不懂得话自行验证一下)
发表于 2016-07-25 22:00:58 回复(1)
关于去掉cat之后的情况:
由图可见,系统对int数组中最后一个int进行了字节填充


发表于 2016-05-02 08:58:05 回复(1)
内存对齐需要参考如下几个参数:
#pragma pack设置的参数
结构体成员本身的大小
结构体中最长成员的大小
如果你考虑问题时少考虑任何上述1个参数,都是错误的理解,我负责地告诉大家。
发表于 2016-04-10 22:50:50 回复(2)
解释一下64位的结果(win-DEV-C-64,或者linux-GCC-64)
类型     字节 对齐模数
int         4       4
double   8      8
对于64位union,除了最长之外还要加一个int的‘union信息’,所以sizeof(union)是20+4=24
然后结构体变为:
struct
{
 类型 字节 对齐模数
 int:  4      4
 union:24  4
 dog    8      8
}
内存对齐图示(有点丑凑合看吧):
这里面有一个前提:首地址为0开始
从28之后需要加到dog的对齐模数倍数的地址
最后因为这里的结构体的对齐模数是4,而24正好是4的倍数,所以后面不需要在补位了
 
编辑于 2015-09-18 15:57:57 回复(1)
typedef 声明新类型名 
typedef union {
    long i;
    int k[5];
    char c;
} DATE;
这段代码意思是声明了一个新类型名DATE,代表共用体
union声明一个共用体,共用体中的变量共享同一段内存,所以共用体所占的内存长度等于最长的成员的长度,即int 数组的长度 为20
结构体data 占用字节数为 4+20+8=32
两者相加为52
发表于 2015-09-11 11:33:58 回复(0)
max以4作为基数,
long i : 1111
int k[5] : 1111 1111 1111 1111 1111
char c : 1
所以,sizeof(max) = 20;

struct data以8作为基数,
int cat : 1111
DATE cow : 1111 1111 1111 1111 1111
double : 1111 1111
所以,sizeof(struct data) = 32;
发表于 2015-06-04 09:20:07 回复(0)

答:DATE是一个union, 变量公用空间. 里面最大的变量类型是int[5], 占用20个字节. 所以它的大小是20

data是一个struct, 每个变量分开占用空间. 依次为int4 + DATE20 + double8 = 32. 所以结果是 20 + 32 = 52.

当然...在某些16位编辑器下, int可能是2字节,那么结果是 int2 + DATE10 + double8 = 20
编辑于 2015-07-30 23:53:27 回复(13)
这道题64位系统答案为64.
      首先看union,根据union内存分配规则,最大的为int k[5],大小为4*5=20,但是long i为8个字节,所以union是以8个字节为一个内存单位,5个int两两为一个内存单元,多出来的int则进行补齐,所以大小为3*8=24.
      接下来看struct,最大为double,所以8字节为一单元,此时当cow看为一个整体,不可看为5个int,所以struct的内存分配为:int cat 大小为4补齐4个字节,cow大小为24,double dog大小为8,所以struct大小为8+24+8=40.
       综上答案为40+24=64.
ps:在union中如果不是long,而是int的话,union大小则为20.

发表于 2019-04-06 18:38:32 回复(0)
补充一点我自己的看法,题目给的是32位,联合体中最大的int k[5]字节数是20 ,正好也是最大对齐数4的整数倍,所以联合体大小是20,第二个结构体嵌套了联合体,应该对齐到联合体的最大对齐数整数倍上,对于int数组按int类型4字节最大对齐数算,结构体内第一个int,偏移量是3,DATE cow 正好在偏移量位4的地方,直接放进去,第三个double类型在偏移量为24的地方,(是最大对齐数8的整数倍)直接放进去,所以最后是32,然后32也是结构体中最大对齐数8的整数倍,所以结构体大小为32,加在一起为52
发表于 2022-08-24 12:08:04 回复(0)
首先此题在32位long 4字节,int 4字节,所以在union中为4字节内存对齐,不是20字节对齐,最大的是int k[5]=20 后面结构体,一楼正解
编辑于 2018-04-05 21:35:22 回复(0)
不知道为什么那么多说52的,我的xcode 64位测试结果是  64
首先union 取最长的变量是20字节,但是他还要跟他最大类型long(8字节)对齐,因此sizeof(max)=24
对于结构体,第一个变量占4字节,第二个是Date的对象,所以占24字节,但是他的初始地址应该是他的最宽类型(long)的整数倍,所以1-4是int的,5-8是补齐的,9-32是cow的,最后还有8个字节是double 因此sizeof(struct data)=40  综上结果是64
发表于 2018-04-04 21:20:35 回复(0)
联合不用对齐吗?
发表于 2017-05-16 07:56:20 回复(1)
编译器进行优化解释减少空间使用
发表于 2017-04-13 16:02:54 回复(1)
sizeof(struct data) 结构体为每个数据类型分配空间,可以同时使用多种类型, 结构体的总大小,必须是内部最大成员的整数倍
发表于 2017-02-16 10:40:54 回复(0)
首先sizeof(max)=20,肯定没有争议,4*5=20;而且32位系统默认为4个字节的对齐方式(不管多少位的,我们都可以用pragma pack(n)设置为n位对齐方式),笔者的系统是64位的,默认对齐为8,通过pragma pack(4)改变对齐方式,使得对齐方式为4字节。
对于sizeof(struct data):开始int为4字节,开始是0偏移,是4的整数倍,所以不要补齐,为4;
DATE为20字节,起始位置的偏移此时为4(前面为int),不要补齐,结果为20+4=24(此时以int类型为对齐大小,不是以20);
保存dog时此时偏移为24,所以依然满足整数倍的要求,直接加上8:24+8=32;
所以结果为4+20+8+20=52;
如果实在要较真,把too结构体的int  cat移到double dog后面,此时结果由于内存对齐,变大为:20+8+4+20=52;因为如果结构体的数据大小比系统默认的对齐字节小就以该字节的大小为对齐大小,如果结构体的数据大小比系统默认的对齐字节大,就以系统默认的大小为对齐方式。
详情可参考:http://blog.csdn.net/monkey_d_feilong/article/details/51685745
发表于 2016-08-27 22:25:17 回复(0)