Intel和微软同时出现的C语言面试题 /iaf ^
>
#pragma pack(8) xg@NQI@7
5s{j=.O
struct s1{ ;]2s,za)qs
short a; SkQswH
long b; EbNd=Z'J
}; pc]J[ S?P
XRN+`J
struct s2{ ^Q<mV*~
char c; W i.5Y{
s1 d; t<iEj"5
long long e; )FN;+"IJ
}; KJn!Ap
e.d
#wyeX
#pragma pack() bpAv1udX-W
W!Gdf^Yy<
问 (.Y/
1.sizeof(s2) = ? rh*sbZ68>E
2.s2的s1中的a后面空了几个字节接着是b? y[};J
vk
K>:]Bx#F7
xgu `Q`~
cf_|nL#9
如果您知道答案请在讨论中写出,以下是部份网友的答案,供参考: #18 FA|
d~J-|yyT
网友rwxybh(行云)的答案: OWp%v_y]
内存布局是 B5%n(,Lx
1*** 11** <6TT)t<h
1111 **** 2-*V=El
1111 1111 J5Z%ImiT^O
^ <`(lyph
所以答案就是24和3 @D^^_1~
u^Ku;RQo
下面是一个测试的程序,试一试就知道了,我用的是VC2005 U @v*0
PXoz*)tk
#pragma pack(8) ?4H#G)F
Z6C=T;w
struct s1{ VXBY8;+Yp
short a; // 2 BYtes pO Iq%0]
long b; // 4 Bytes eDI=nSo
}; 8LkP)]4^sO
struct s2{ q<W=#Sx
char c; // 1 Byte W<ZK,kv
s1 d; // 8 Bytes ^ >x|z.
long long e; // 8 Bytes 6DIZ@ oi
}; g6t"mkMY
L
// 1*** 11** 1+;C`bnA
// 1111 **** M,5j5<7
// 1111 1111 Psur a$:
// u9woEe?
Jq.lT(E8D
// 00 01 02 03 04 05 06 07 620%Z*
// 00 01 02 03 04 05 06 07 IzOYduJ.
// 00 01 02 03 04 05 06 07 4BYE1fUzd
// 3f Xv4R;!:
#pragma pack() \`V$
'B{.
Qhi '')Q
int main(int argc, char* argv[]) Y/<lWbj*A
{ moj]j`P5a
s2 a; /
O/`<
char *p = (char *)&a; 7M_U2cd|TD
for(int i=0;i<24;++i) gbeghLP[?
p = (char)(i%8); YpAg
printf("%d\n",sizeof(a)); |'ln?D:&
printf("c=0x%lx\n",a.c); 8b.u'r174
printf("d.a=0x%x\n",a.d.a); WW2Ob*
printf("d.b=0x%x\n",a.d.b); <:FP4e
"(
printf("e=0x%llx\n",a.e); kqYa*| l
return 0; fA%z*\
} 3ya1'qUC
结果: 5RH2"*8T
24 k#Of]mXXz
c=0x0 ,Y?sfp
d.a=0x504 %
}|cb7l
d.b=0x3020100 yH 9!GS#
e=0x706050403020100 LTV{{Z+
ZoB*0H-
9//+Bh
网友 redleaves (ID最吊的网友)的答案和分析: p9U?!L!y
B&+`)E{KB
如果代码: Yb i%od&
#pragma pack(8) OJN2z
struct S1{ ev0oO+u
char a; w@-PqsF
long b; X:a`B(@S
}; N..j{FE
struct S2 { /yz=Cj oz
char c; L9Z;:``p
struct S1 d; Rgo rkZlVM
long long e; <^~FLjsfg
}; .?p\n7
#pragma pack() /&& 2u7*
sizeof(S2)结果为24. P7ph}mB
成员对齐有一个重要的条件,即每个成员分别对齐.即每个成员按自己的方式对齐. etT +
也就是说上面虽然指定了按8字节对齐,但并不是所有的成员都是以8字节对齐.其对齐的规则是,每个成员按其类型的对齐参数(通常是这个类型的大小)和指定对齐参数(这里是8字节)中较小的一个对齐.并且结构的长度必须为所用过的所有对齐参数的整数倍,不够就补空字节. H.<a`mm8
e~ aqaY~}
S1中,成员a是1字节默认按1字节对齐,指定对齐参数为8,这两个值中取1,a按1字节对齐;成员b是4个字节,默认是按4字节对齐,这时就按4字节对齐,所以sizeof(S1)应该为8; JjpRHw8\
S2中,c和S1中的a一样,按1字节对齐,而d 是个结构,它是8个字节,它按什么对齐呢?对于结构来说,它的默认对齐方式就是它的所有成员使用的对齐参数中最大的一个,S1的就是4.所以,成员d就是按4字节对齐.成员e是8个字节,它是默认按8字节对齐,和指定的一样,所以它对到8字节的边界上,这时,已经使用了12个字节了,所以又添加了4个字节的空,从第16个字节开始放置成员e.这时,长度为24,已经可以被8(成员e按8字节对齐)整除.这样,一共使用了24个字节. n%R;-?*v
a b FlfI9mm
S1的内存布局:11**,1111, \~d";~Y`
c S1.a S1.b d V@7KsB
S2的内存布局:1***,11**,1111,****11111111 K3uG2g(>2
oRKEJNps
这里有三点很重要: kg][qn|>J]
1.每个成员分别按自己的方式对齐,并能最小化长度 jV#ahNq;
2.复杂类型(如结构)的默认对齐方式是它最长的成员的对齐方式,这样在成员是复杂类型时,可以最小化长度 n?\ nn3
3.对齐后的长度必须是成员中最大的对齐参数的整数倍,这样在处理数组时可以保证每一项都边界对齐 Mypc3
&R|/t:DN
fP
tm0.r
网友xue23(xue23) 的答案和分析: &1l=X]%
IKMeJ(:S
有程序查一下各个变量的内存地址得知: WwF~d+>|C
各个变量在内存中的位置为 )15Z#`x
c***aa** ONNpiK-
bbbb**** ,:~0F^z
dddddddd {U
'd}Q
测试代码为: 4Wy<?O2
s2 ss; A7!g
cout << "ss.c = " << &ss << endl ; 72sD0)?A
cout << "ss.d.a = " <<&ss.d.a << endl; 8Y0"Cejq
cout << "ss.d.b = " <<&(ss.d.b) < cout << "ss.d = " <<&ss.e << endl; PiV7*F4qI.
print out 各个变量的内存地址不就可以看出来了吗。 Wk:hFHs3
E_F5(xSA
所以答案是24,2. }R3=fbe,\
nJRS.xs
但是我的想像中应该是这样的分布情况: mS#zraJn5
c******* J$4wL
F3
aa**bbbb H/M Au7
dddddddd
{7!UQrm<
)eUW5
tS
不知为什么会c和a放在一起,组成8位长度。