Intel和微软同时出现的C语言面试题 P?xA$_+
#pragma pack(8) %z=`JhE"Q
(yfXMp,x
struct s1{ ]XY0c6
<
short a; 4AJ9`1d4
long b; '\@WN]
}; ^[0"vtb
8*vFdoE_oO
struct s2{ li@kLh
char c; Urn
s1 d; :u
AjV
long long e; tO7I&LNE
}; bZu$0IG
L,6MF,vx
#pragma pack() 6I"C~&dt
ad9EG#mD#
问 Trpgx
1.sizeof(s2) = ? )x)gHY8;
2.s2的s1中的a后面空了几个字节接着是b? %
^e@`0L
3<+z46`?
a`s/ qi
=ydpU<aS
如果您知道答案请在讨论中写出,以下是部份网友的答案,供参考: <W?WUF
7O"hiDQ
网友rwxybh(行云)的答案: ("b*? : B
内存布局是 %Or2iuO%-,
1*** 11** _nP)uU$
1111 **** w\p9J0
1111 1111 DDWp4`CS|
[Q|M/|mnR1
所以答案就是24和3 9Kx<\)-GMD
@bE~@4mOu
下面是一个测试的程序,试一试就知道了,我用的是VC2005 % oR>Uo
@FU~1u3d
#pragma pack(8) g(nK$,c
b22LT52
struct s1{ ^zHRSO
short a; // 2 BYtes
A=0@UqM
long b; // 4 Bytes 7r['
}; ?@>;/@
struct s2{ YlrB@mE0n$
char c; // 1 Byte Hl/7(FJqc>
s1 d; // 8 Bytes ~oo'ky*H!
long long e; // 8 Bytes my4\mi6P
}; w1cw1xX*
// 1*** 11** d[S#Duz<&
// 1111 **** Vli3>K&
// 1111 1111 I=o'+>az
// %OEq,Tb
VE*j*U
j
// 00 01 02 03 04 05 06 07 #%4=)M>^
// 00 01 02 03 04 05 06 07 rtus`A5p
// 00 01 02 03 04 05 06 07 SYeE) mI
// <>n9'i1
#pragma pack() so*/OBte
IqNpLh|[
int main(int argc, char* argv[]) 1TIlINlJ
{ m9woredS,
s2 a; >gnF]<
char *p = (char *)&a; qfa}3k8et
for(int i=0;i<24;++i) ~o i)Lf1
p = (char)(i%8); l0:5q?g
printf("%d\n",sizeof(a)); ld95[cTP
printf("c=0x%lx\n",a.c); 1#q^uqO0
printf("d.a=0x%x\n",a.d.a); 5N1}Ns
printf("d.b=0x%x\n",a.d.b); aLYLd/ KV
printf("e=0x%llx\n",a.e); 'g~@"9'oe
return 0; X>{p}vtvf>
} R5gado
结果: dl_{iMhF&E
24 u0g*O]Y
c=0x0 @0D![oA
d.a=0x504 "9ue76
d.b=0x3020100 @+:4J_N
e=0x706050403020100 gvGi%gq
c_Tzyh7l4
d@Q][7
网友 redleaves (ID最吊的网友)的答案和分析: r^Y~mq
O k*Z
如果代码: >T QZk4$
#pragma pack(8) {\L|s5=yr
struct S1{ @C=M
UT-!
char a; #52NsVaT@
long b; |by@ :@*y
}; /p 5=i
struct S2 { vf N#NY6
char c; M%|f+u &
struct S1 d; ikIzhUWE
long long e; kZv*rWAm
}; 9ad6uTc
#pragma pack() C.(
yd$,
sizeof(S2)结果为24. f1J%]g!
成员对齐有一个重要的条件,即每个成员分别对齐.即每个成员按自己的方式对齐. r6MB"4xd
也就是说上面虽然指定了按8字节对齐,但并不是所有的成员都是以8字节对齐.其对齐的规则是,每个成员按其类型的对齐参数(通常是这个类型的大小)和指定对齐参数(这里是8字节)中较小的一个对齐.并且结构的长度必须为所用过的所有对齐参数的整数倍,不够就补空字节. V_f`0\[x
=hGJAU
S1中,成员a是1字节默认按1字节对齐,指定对齐参数为8,这两个值中取1,a按1字节对齐;成员b是4个字节,默认是按4字节对齐,这时就按4字节对齐,所以sizeof(S1)应该为8; '#<> "|
S2中,c和S1中的a一样,按1字节对齐,而d 是个结构,它是8个字节,它按什么对齐呢?对于结构来说,它的默认对齐方式就是它的所有成员使用的对齐参数中最大的一个,S1的就是4.所以,成员d就是按4字节对齐.成员e是8个字节,它是默认按8字节对齐,和指定的一样,所以它对到8字节的边界上,这时,已经使用了12个字节了,所以又添加了4个字节的空,从第16个字节开始放置成员e.这时,长度为24,已经可以被8(成员e按8字节对齐)整除.这样,一共使用了24个字节. Y&g&n o_
a b drIK(u\_
S1的内存布局:11**,1111, l2s{~ IC
c S1.a S1.b d pC^2Rzf
S2的内存布局:1***,11**,1111,****11111111 :~D];m
U!0E_J
这里有三点很重要: hbfsHT
1.每个成员分别按自己的方式对齐,并能最小化长度 ;_N"Fdl
2.复杂类型(如结构)的默认对齐方式是它最长的成员的对齐方式,这样在成员是复杂类型时,可以最小化长度 :3 y_mf>
3.对齐后的长度必须是成员中最大的对齐参数的整数倍,这样在处理数组时可以保证每一项都边界对齐 $kl$D"*0
h R~v
@hsbq
网友xue23(xue23) 的答案和分析: JhJLqb@q
$_FZn'Db6
有程序查一下各个变量的内存地址得知: rVcBl4&1*g
各个变量在内存中的位置为 OX^3Q:Z=
c***aa** s/h7G}Mu
bbbb**** ul=7>";=|
dddddddd ;s}3e#$L
测试代码为: 7k~Lttuk
s2 ss; ]F+K|X9-
cout << "ss.c = " << &ss << endl ; sf)W~Lx5a
cout << "ss.d.a = " <<&ss.d.a << endl; :".w{0l@
cout << "ss.d.b = " <<&(ss.d.b) < cout << "ss.d = " <<&ss.e << endl; Ihqs%;V
print out 各个变量的内存地址不就可以看出来了吗。 c
D7FfJ
fv2=B)8$
所以答案是24,2. a:b^!H>#
M(2`2-/xh
但是我的想像中应该是这样的分布情况: mW +tV1XjG
c******* .8(%4ejJ(
aa**bbbb ;UpJ=?W
dddddddd :Eo8v$W\RB
/>F.Nsujy
不知为什么会c和a放在一起,组成8位长度。