Intel和微软同时出现的C语言面试题 `Rdm-[&
#pragma pack(8) j6,ZEm
IF +i3#$
struct s1{ 6ATtW+sN ]
short a; Ox#Q2W@Uy
long b; KT.?Xp:z
}; kJAn4I.l
;@nFVy>U
struct s2{ $LHa?3
char c; /?6gdN
s1 d; M0'
a9.d
long long e; G\;}w
}; TS"D]Txs
EQe5JFR
#pragma pack() ]}mxY
vu_i
GI7=xh
问 4<X!<]3]
1.sizeof(s2) = ? |3{&@7
2.s2的s1中的a后面空了几个字节接着是b? \@~UDP]7
5 #]4YI;
K?4FT$9G
=l9T7az
如果您知道答案请在讨论中写出,以下是部份网友的答案,供参考: SMf+qiM-E
F=)&98^v$_
网友rwxybh(行云)的答案: j+8TlVur
内存布局是 J RPSvP\
1*** 11** +y#T?!jQYj
1111 **** O%f8I'u$
1111 1111 }K(o9$V ^!
UzKFf&-:;K
所以答案就是24和3 f{lZKfrp
MDRe(rF=
下面是一个测试的程序,试一试就知道了,我用的是VC2005 )B!d,HKt;
A
K/z6XGy
#pragma pack(8) Zw]
?.
XTeb9h)3
struct s1{ =6=_/q2
short a; // 2 BYtes %5
long b; // 4 Bytes _J]2~b
}; r,N[ )@
struct s2{ nW+YOX|+
char c; // 1 Byte up%Z$"Y
s1 d; // 8 Bytes l+y}4k=/
long long e; // 8 Bytes Hwm?#6\5
}; jko"MfJ
// 1*** 11** 2uk x (Z
// 1111 **** cE{ =(OQ
// 1111 1111 M]HgIL@9#
// 6<5Jq\-h
&,i~ cG?
// 00 01 02 03 04 05 06 07 &s)0z)mR8&
// 00 01 02 03 04 05 06 07 3,);0@I
// 00 01 02 03 04 05 06 07 fA! 6sB
// q6wr=OWD
#pragma pack() G_ Ay
y_}SK6{
int main(int argc, char* argv[]) o0pT6N)
{ *o' 4,+=am
s2 a; ecX/K.8l
char *p = (char *)&a; R:aYL~
for(int i=0;i<24;++i) ^+R:MBK
p = (char)(i%8); *mBJ?{ !
printf("%d\n",sizeof(a)); `BnP[jF
printf("c=0x%lx\n",a.c); l9/:FiJ_
printf("d.a=0x%x\n",a.d.a); W3Ulewa
printf("d.b=0x%x\n",a.d.b); b>~RSO*
printf("e=0x%llx\n",a.e); z]Acs
return 0; VG*'"y*%w
} sFb4`
结果: f]d!hz!
24 d
`j?7Z
c=0x0 >&H~nGP.
d.a=0x504 t#<KxwhcN
d.b=0x3020100 hN(L@0)
e=0x706050403020100 Z,WW]Y,$
{@r*+~C3
:w?7j_p#
网友 redleaves (ID最吊的网友)的答案和分析: WwW^[k (X
~4)Y#IxL
如果代码: *(*+`qZL{(
#pragma pack(8) [.q(h/b
struct S1{ vZajT!h
char a;
'H FK Bp
long b; j[P8
}; aQcN&UA@
struct S2 { kd;'}x=5yP
char c; 9.0WKcwg
struct S1 d; =J@`0H"
long long e; 4R +P
}; @+^c"=d1S
#pragma pack() xaL#MIR"u"
sizeof(S2)结果为24. x.EgTvA&d
成员对齐有一个重要的条件,即每个成员分别对齐.即每个成员按自己的方式对齐. h)E|?b_
也就是说上面虽然指定了按8字节对齐,但并不是所有的成员都是以8字节对齐.其对齐的规则是,每个成员按其类型的对齐参数(通常是这个类型的大小)和指定对齐参数(这里是8字节)中较小的一个对齐.并且结构的长度必须为所用过的所有对齐参数的整数倍,不够就补空字节. eO{@@?/y
u fw cF*
S1中,成员a是1字节默认按1字节对齐,指定对齐参数为8,这两个值中取1,a按1字节对齐;成员b是4个字节,默认是按4字节对齐,这时就按4字节对齐,所以sizeof(S1)应该为8; W3LP
~
S2中,c和S1中的a一样,按1字节对齐,而d 是个结构,它是8个字节,它按什么对齐呢?对于结构来说,它的默认对齐方式就是它的所有成员使用的对齐参数中最大的一个,S1的就是4.所以,成员d就是按4字节对齐.成员e是8个字节,它是默认按8字节对齐,和指定的一样,所以它对到8字节的边界上,这时,已经使用了12个字节了,所以又添加了4个字节的空,从第16个字节开始放置成员e.这时,长度为24,已经可以被8(成员e按8字节对齐)整除.这样,一共使用了24个字节. D{AFL.r{
a b 4YJ=q% G
S1的内存布局:11**,1111, z/1hqxHl
c S1.a S1.b d ma9ADFFT
S2的内存布局:1***,11**,1111,****11111111 Q[s2}Z!N;
+$(0w35V5
这里有三点很重要: |5xz l
1.每个成员分别按自己的方式对齐,并能最小化长度 )o8g=7Jm
2.复杂类型(如结构)的默认对齐方式是它最长的成员的对齐方式,这样在成员是复杂类型时,可以最小化长度 ">6&+^BN'
3.对齐后的长度必须是成员中最大的对齐参数的整数倍,这样在处理数组时可以保证每一项都边界对齐 *?8RXer
`)[dVfxA
abZdGnc
网友xue23(xue23) 的答案和分析: M^ 5e~y
w3#`1T`N
有程序查一下各个变量的内存地址得知: V:\]cGA{
各个变量在内存中的位置为 U1Yo7nVf
c***aa** 0yHjrxc$
bbbb**** 'XTs
-=
dddddddd h#{T}[
测试代码为: 93I'cWN
s2 ss; ypA: P
cout << "ss.c = " << &ss << endl ; EDN(eh(_
cout << "ss.d.a = " <<&ss.d.a << endl; +{6`F1MO
cout << "ss.d.b = " <<&(ss.d.b) < cout << "ss.d = " <<&ss.e << endl; nC~fvyd<P
print out 各个变量的内存地址不就可以看出来了吗。 :l~E E!
~|R[O^9B
所以答案是24,2. >I-g[*
>38
Lt\
但是我的想像中应该是这样的分布情况: C6)R#
c******* a9[< ^
aa**bbbb 2cjEex:&
dddddddd Bn-J_-%M
+a]j[#
不知为什么会c和a放在一起,组成8位长度。