Intel和微软同时出现的C语言面试题 F+v? 2|03
#pragma pack(8) wT3QSJ
s>76?Q:i
struct s1{ <0k(d:H-
short a; M
E4MZt:>
long b; Z"]
ben
}; WDWb7
j'#W)dp(
struct s2{ CKmoC0.
char c; MjQKcL4%7
s1 d; I[WW1P5
long long e; b~y1'|}g
}; w<.{(1:v
`oXUVr
#pragma pack() O>lF{yO0`
7Ha
+@
问 (zCas}YAKI
1.sizeof(s2) = ? mc~d4<$`!
2.s2的s1中的a后面空了几个字节接着是b? n,bZj<3t
=YE"6iU
p&_Kb\}U
#]q<fhJhr$
如果您知道答案请在讨论中写出,以下是部份网友的答案,供参考: ^mm:u<Yt
b6'%nR*f
网友rwxybh(行云)的答案: +8]}'6m
内存布局是 @{j'Pf'
1*** 11** v@&&5J|
1111 **** (|Y[5O)
1111 1111 [^A 93F
oIAP dn
所以答案就是24和3 ?r"m*fY%
3^xTZ*G
下面是一个测试的程序,试一试就知道了,我用的是VC2005 k?o(j/
Azxy!gDT"
#pragma pack(8) ^
RU"v>
"|gNNmr
struct s1{ bT@3fuL4
short a; // 2 BYtes P"cc$lB~ I
long b; // 4 Bytes hS OAjS
}; X48Q{E+
struct s2{ N^Xb_jg;J
char c; // 1 Byte G sm5L<rx
s1 d; // 8 Bytes .-k\Q}D
long long e; // 8 Bytes o;7!$v>uK
}; J'sVT{@GS
// 1*** 11** ^!3Sz1
// 1111 **** ]HgAI$aA,
// 1111 1111 !rlN|HB
// D[x0sly
l
Ztq_* Fl
// 00 01 02 03 04 05 06 07 HWi0m/J
// 00 01 02 03 04 05 06 07 SuMK=^>%
// 00 01 02 03 04 05 06 07 I@08F
// rg]eSP3W
#pragma pack() r77?s?
?dVF@
int main(int argc, char* argv[]) T_lexX[\
{ (x2I*<7P
s2 a; O~.A}
char *p = (char *)&a; /lC n^E6-
for(int i=0;i<24;++i) ^sY ]N77
p = (char)(i%8); Q7gBxp
printf("%d\n",sizeof(a)); N J9H=
printf("c=0x%lx\n",a.c); a*0gd-e0@
printf("d.a=0x%x\n",a.d.a); m
jC6(?V
printf("d.b=0x%x\n",a.d.b); wLAGe'GX
printf("e=0x%llx\n",a.e); Nc()$Nl8
return 0; MoIVval/
} RAxAy{
结果: oC#@9>+@+"
24 9s5gi+l_O
c=0x0 m2AA:u_*j
d.a=0x504 8p }E
d.b=0x3020100 (y7U}Sb'
e=0x706050403020100 B9`nV.a
Ev|2bk \
mWZoo/xtT
网友 redleaves (ID最吊的网友)的答案和分析: #(FG+Bk
+e. bO5Y
如果代码: pP;GDW4
#pragma pack(8) D:sQHJ.y
struct S1{ &]iX>m.
char a; o
/AEp)8
long b; 'KMyaEh.u
}; -)(HG)3
struct S2 { \/I@&$"F
char c; / Li?;H
struct S1 d; m*tmmP4R
long long e; /v7U~i5
}; HA&][%^
#pragma pack() 'oBT*aL
sizeof(S2)结果为24. ~rN~Ql%S
成员对齐有一个重要的条件,即每个成员分别对齐.即每个成员按自己的方式对齐. GxL5yeN@(
也就是说上面虽然指定了按8字节对齐,但并不是所有的成员都是以8字节对齐.其对齐的规则是,每个成员按其类型的对齐参数(通常是这个类型的大小)和指定对齐参数(这里是8字节)中较小的一个对齐.并且结构的长度必须为所用过的所有对齐参数的整数倍,不够就补空字节. #uVH~P5TM
i=#<0! m
S1中,成员a是1字节默认按1字节对齐,指定对齐参数为8,这两个值中取1,a按1字节对齐;成员b是4个字节,默认是按4字节对齐,这时就按4字节对齐,所以sizeof(S1)应该为8; 'Pk (
1:
S2中,c和S1中的a一样,按1字节对齐,而d 是个结构,它是8个字节,它按什么对齐呢?对于结构来说,它的默认对齐方式就是它的所有成员使用的对齐参数中最大的一个,S1的就是4.所以,成员d就是按4字节对齐.成员e是8个字节,它是默认按8字节对齐,和指定的一样,所以它对到8字节的边界上,这时,已经使用了12个字节了,所以又添加了4个字节的空,从第16个字节开始放置成员e.这时,长度为24,已经可以被8(成员e按8字节对齐)整除.这样,一共使用了24个字节. }:P/eY
a b W2J"W=:z
S1的内存布局:11**,1111, }bz v&k
c S1.a S1.b d |Tuk9d4]
S2的内存布局:1***,11**,1111,****11111111 \b?z\bC56
rIR~YMv!
这里有三点很重要: R@-rc|FunJ
1.每个成员分别按自己的方式对齐,并能最小化长度 glbU\K> >
2.复杂类型(如结构)的默认对齐方式是它最长的成员的对齐方式,这样在成员是复杂类型时,可以最小化长度 _[zO?Div[
3.对齐后的长度必须是成员中最大的对齐参数的整数倍,这样在处理数组时可以保证每一项都边界对齐 nKC$
KC
yxh8sAZ
UaA6
网友xue23(xue23) 的答案和分析: .e%PK[o
2JwR?<n{
有程序查一下各个变量的内存地址得知: # kl?ww U
各个变量在内存中的位置为 'kPc`)\
c***aa** {]]qd!,
bbbb**** D'2&'7-sm\
dddddddd E#X(0(A)
测试代码为: z@iu$DZ
s2 ss; l'n"iQ!G
cout << "ss.c = " << &ss << endl ; 5rK7nLb
cout << "ss.d.a = " <<&ss.d.a << endl; 1nhC! jDD
cout << "ss.d.b = " <<&(ss.d.b) < cout << "ss.d = " <<&ss.e << endl; ;0( |06=
print out 各个变量的内存地址不就可以看出来了吗。 *6=2UJcJ
,{MA90!
所以答案是24,2. /MKcS%/H/
gF+Uj( d
但是我的想像中应该是这样的分布情况: WQv%57+
c******* @U08v_,
aa**bbbb #G%[4.$n.
dddddddd 9ar+P h@*
TC;2K,.#k
不知为什么会c和a放在一起,组成8位长度。