Intel和微软同时出现的C语言面试题 YZ%Hu)
#pragma pack(8) B'^:'uG
L#vI=GpL,r
struct s1{ Ok n(pJ0
short a; tK&'<tZh
long b; 5Ri6Z#qm
}; F <hJp,q9
kWdi595
struct s2{ IpP~Uz
char c; qhT@;W/X
s1 d; 7O,U?p
long long e; !9xp cQ>
}; ~ o1x;Y6
271&i
#pragma pack() tU_y6
>Wz;ySEz
问 @xB*KyUW
1.sizeof(s2) = ? yRo-EP
2.s2的s1中的a后面空了几个字节接着是b? :O(^w}sle
^5=B`aich
{J^lX/D
d6W SL;$
如果您知道答案请在讨论中写出,以下是部份网友的答案,供参考: c+2FC@q{l
WJ_IuX51'
网友rwxybh(行云)的答案: _6wFba@>/n
内存布局是 ;\p KDPr
1*** 11** <n(*Xak{a
1111 **** _Gu-
uuy
1111 1111 Vb9',a?#n
.nyfYa+
所以答案就是24和3 1&e} ms
h[PYP5{L
下面是一个测试的程序,试一试就知道了,我用的是VC2005 }fKSqB]T-
=|9H
#pragma pack(8) D}vmwg@3
gB<3-J1R
struct s1{ 9Lr'YRl[W
short a; // 2 BYtes rD*sl}
long b; // 4 Bytes y
K"kEA[;
}; %Qj;, #z
struct s2{
8stwg'
char c; // 1 Byte =9j8cC5y
s1 d; // 8 Bytes _)\c&.p]f
long long e; // 8 Bytes s>^dxF!+
}; /Ml.}7&
// 1*** 11** v'e[GB0
// 1111 **** ;X?mmv'
// 1111 1111 X,LD
// ` \+@Fwfx
7e<c$t#H
// 00 01 02 03 04 05 06 07 p ZZc:\fJ
// 00 01 02 03 04 05 06 07 _r2J7&
// 00 01 02 03 04 05 06 07 7^g&)P
// x:QgjK
#pragma pack() 2 aL)
mQY_`&Jq
int main(int argc, char* argv[]) e#E2>Bj;
{ VqS#waNrx
s2 a; kcQ'$<Mz<
char *p = (char *)&a; n/h,Lr)Z
for(int i=0;i<24;++i) %?m$`9yU
p = (char)(i%8); HQB(*
printf("%d\n",sizeof(a)); {Lm~r+
U
printf("c=0x%lx\n",a.c); &\Amn?Iq
printf("d.a=0x%x\n",a.d.a); 8HP6+c%
printf("d.b=0x%x\n",a.d.b); sq;s]@~
printf("e=0x%llx\n",a.e); Ybn`3
return 0; G>q(iF'
} Ud!4"<C_
结果:
7[.6axL
24 `P9XqWr
c=0x0 P><o,s"v
d.a=0x504 +-G<c6 |
d.b=0x3020100 wR^ RM(1
e=0x706050403020100 qkC/\![@
VH[hsj
4fKC 6UR
网友 redleaves (ID最吊的网友)的答案和分析: q=#}
yEG
HvVts\f
如果代码: #H0dZ.$b0
#pragma pack(8)
K#U<ib-v
struct S1{ T8HF|%I
char a; KhMSL
long b; VP6ZiQ|
}; yUp,NfS]o
struct S2 { nH<eR)0
char c; rs~wv('
struct S1 d; ObiT-D?)g
long long e; Z"AQp _
}; rSJ9v:
#pragma pack() [B|MlrZ
sizeof(S2)结果为24. M{*Lp6h
成员对齐有一个重要的条件,即每个成员分别对齐.即每个成员按自己的方式对齐. |gU(s
也就是说上面虽然指定了按8字节对齐,但并不是所有的成员都是以8字节对齐.其对齐的规则是,每个成员按其类型的对齐参数(通常是这个类型的大小)和指定对齐参数(这里是8字节)中较小的一个对齐.并且结构的长度必须为所用过的所有对齐参数的整数倍,不够就补空字节. p1|f<SF')
o9H^?Rut
S1中,成员a是1字节默认按1字节对齐,指定对齐参数为8,这两个值中取1,a按1字节对齐;成员b是4个字节,默认是按4字节对齐,这时就按4字节对齐,所以sizeof(S1)应该为8; nG;8:f`
S2中,c和S1中的a一样,按1字节对齐,而d 是个结构,它是8个字节,它按什么对齐呢?对于结构来说,它的默认对齐方式就是它的所有成员使用的对齐参数中最大的一个,S1的就是4.所以,成员d就是按4字节对齐.成员e是8个字节,它是默认按8字节对齐,和指定的一样,所以它对到8字节的边界上,这时,已经使用了12个字节了,所以又添加了4个字节的空,从第16个字节开始放置成员e.这时,长度为24,已经可以被8(成员e按8字节对齐)整除.这样,一共使用了24个字节. xQ@^$_
a b |JVk&8
?8
S1的内存布局:11**,1111, _~T!9
c S1.a S1.b d 1u6^z
S2的内存布局:1***,11**,1111,****11111111 _-#'j2
ka3u&3"
这里有三点很重要: ;]pJj6J&v
1.每个成员分别按自己的方式对齐,并能最小化长度 D`VM6/iQR
2.复杂类型(如结构)的默认对齐方式是它最长的成员的对齐方式,这样在成员是复杂类型时,可以最小化长度 ph-ATJ"
3.对齐后的长度必须是成员中最大的对齐参数的整数倍,这样在处理数组时可以保证每一项都边界对齐 PZ*pQ=`
%Jrt4sg[j-
67VT\f
网友xue23(xue23) 的答案和分析: di>cMS 4 c
L*~J%7
有程序查一下各个变量的内存地址得知: xa
pq*oj
各个变量在内存中的位置为 1Tm^
c***aa** T16{_
bbbb**** $]/Zxd
dddddddd jb^N|zb
测试代码为: x(eb5YS
s2 ss; ruazOmnn~
cout << "ss.c = " << &ss << endl ; mzf+Cu:`v
cout << "ss.d.a = " <<&ss.d.a << endl; k0Uyf~p~
cout << "ss.d.b = " <<&(ss.d.b) < cout << "ss.d = " <<&ss.e << endl; !H}vu]R
print out 各个变量的内存地址不就可以看出来了吗。 t>[KVVg
W
(4Zts0O\
所以答案是24,2. /\WQxe
7K5P8N
,
但是我的想像中应该是这样的分布情况: P`e!Z:
c******* 7Ddaf>
aa**bbbb FGh]S-A
dddddddd N+y&,N,
nVI!@qW
不知为什么会c和a放在一起,组成8位长度。