Intel和微软同时出现的C语言面试题 [k\VUg:P
#pragma pack(8) PWl;pBo
y4jiOhF<d
struct s1{ i4D]>
short a; #oTVfY#
long b; 6
:3Id
}; e8 ]CB
F]6G<6T[
struct s2{ I2CI9,0
char c; jy.L/s
s1 d; 'XKfKv >;
long long e; A"M;kzAfHM
}; z_xy*Iif
,jC~U s<
#pragma pack() zqdkt `
drjNK!XL@
问 ^2Cqy%x-
1.sizeof(s2) = ? 9D\E0YG X/
2.s2的s1中的a后面空了几个字节接着是b? 98 R/^\
D? %*L
)J @[8 x`
J[?oV;O
如果您知道答案请在讨论中写出,以下是部份网友的答案,供参考: jRC{8^98
\Qah*1
网友rwxybh(行云)的答案: jm<^WQ%Cc
内存布局是 0qFO+nC
1*** 11** )
6QJZ$
1111 **** jW8ad{
1111 1111 8/R$}b><
P{K\}+9F
所以答案就是24和3 5,MM`:{{
yO7H!}y_
下面是一个测试的程序,试一试就知道了,我用的是VC2005 A2\hmp@A@7
cD`?"n
#pragma pack(8) $m5Iv_
N<<wg{QO
struct s1{ #@BhGB`9Qt
short a; // 2 BYtes yxu7YGp%
long b; // 4 Bytes |khFQ(
}; h='&^1
struct s2{ ""
^n^$
char c; // 1 Byte /7Sg/d%c
s1 d; // 8 Bytes U~yPQ8jD
long long e; // 8 Bytes 5g-1pzP9
}; ],!}|
// 1*** 11** 3t9+Y dNKU
// 1111 **** ZKt{3P
// 1111 1111 B]yO
// -V2`[k
.{t5_,P
// 00 01 02 03 04 05 06 07 b)Nd}6}<?
// 00 01 02 03 04 05 06 07 j07A>G-=
// 00 01 02 03 04 05 06 07 }KUK|p5
// /V+7:WDj
#pragma pack() k}g4?
qmnl
int main(int argc, char* argv[]) 8SroA$^n
{ "kcix!}&
s2 a; [Y`E"1f2
char *p = (char *)&a; ]Gm4gd`
for(int i=0;i<24;++i) <^>
nR3E
p = (char)(i%8); ~u0<c:C^
printf("%d\n",sizeof(a)); /<T{g0s
printf("c=0x%lx\n",a.c); w]xr
~D+
printf("d.a=0x%x\n",a.d.a); #lMIs4i.
printf("d.b=0x%x\n",a.d.b); 8v/,<eARJ
printf("e=0x%llx\n",a.e); MX#LtCG#V
return 0; ZZkc) @
} DS4y@,/)'
结果: GKWsJO5 n
24 +}udIi3:l
c=0x0 T"H"m4{'
d.a=0x504 "\+\,C
d.b=0x3020100 -XnIDXM
e=0x706050403020100 &$T7eOiZ
:/Pxf N5
%=K [C
网友 redleaves (ID最吊的网友)的答案和分析: "+O/OKfR0
_Ad63.Uq))
如果代码: h]i vXF*
#pragma pack(8) XkUwO ]
struct S1{ yZ=O+H
char a; *=O3kUoL
long b; >f&L7@
}; dlZ2iDQ%
struct S2 { dhP")@3K;p
char c; '?I3&lYz{
struct S1 d; Lf<urIF
long long e; \L?A4Qx)_
}; h~%8p
]
#pragma pack() vY4}vHH2
sizeof(S2)结果为24. WyB^b-QmDh
成员对齐有一个重要的条件,即每个成员分别对齐.即每个成员按自己的方式对齐. 0RSzDgX
也就是说上面虽然指定了按8字节对齐,但并不是所有的成员都是以8字节对齐.其对齐的规则是,每个成员按其类型的对齐参数(通常是这个类型的大小)和指定对齐参数(这里是8字节)中较小的一个对齐.并且结构的长度必须为所用过的所有对齐参数的整数倍,不够就补空字节. mcQ
A'
pR2U&OA
S1中,成员a是1字节默认按1字节对齐,指定对齐参数为8,这两个值中取1,a按1字节对齐;成员b是4个字节,默认是按4字节对齐,这时就按4字节对齐,所以sizeof(S1)应该为8; wLI1qoDM
S2中,c和S1中的a一样,按1字节对齐,而d 是个结构,它是8个字节,它按什么对齐呢?对于结构来说,它的默认对齐方式就是它的所有成员使用的对齐参数中最大的一个,S1的就是4.所以,成员d就是按4字节对齐.成员e是8个字节,它是默认按8字节对齐,和指定的一样,所以它对到8字节的边界上,这时,已经使用了12个字节了,所以又添加了4个字节的空,从第16个字节开始放置成员e.这时,长度为24,已经可以被8(成员e按8字节对齐)整除.这样,一共使用了24个字节. %'. x vC
a b eFy
{VpO+
S1的内存布局:11**,1111, >*B59+1P
c S1.a S1.b d +,7vbs3
S2的内存布局:1***,11**,1111,****11111111 _I,GH{lh I
l%0-W
这里有三点很重要: c*<BU6y
1.每个成员分别按自己的方式对齐,并能最小化长度 "ig)7X+Wz|
2.复杂类型(如结构)的默认对齐方式是它最长的成员的对齐方式,这样在成员是复杂类型时,可以最小化长度 ~A%+oa*2~
3.对齐后的长度必须是成员中最大的对齐参数的整数倍,这样在处理数组时可以保证每一项都边界对齐 ?c"iV
^g2Vz4u
M'X,7hZ
网友xue23(xue23) 的答案和分析: t5 ^hZZ
Mg}/gO%o
有程序查一下各个变量的内存地址得知: !H)!b#_
各个变量在内存中的位置为 'O2/PU2_
c***aa** hfc~HKLC
bbbb**** )3|a_
dddddddd hH05p!2
测试代码为: &Vpr[S@:{
s2 ss; C^_m>H3b
cout << "ss.c = " << &ss << endl ; (*vBpJyz%
cout << "ss.d.a = " <<&ss.d.a << endl; plr3&T~,&S
cout << "ss.d.b = " <<&(ss.d.b) < cout << "ss.d = " <<&ss.e << endl; kbH@h2Ww
print out 各个变量的内存地址不就可以看出来了吗。 L|b[6[XTHL
lc [)Ev
所以答案是24,2. p,(W?.ZDN?
c*R\fQd
但是我的想像中应该是这样的分布情况: Ed-3-vJej6
c******* g#1Y4
aa**bbbb ]TtID4qL
dddddddd muK.x7zyl
e6 <9`Xg
不知为什么会c和a放在一起,组成8位长度。