Intel和微软同时出现的C语言面试题 HlV3rYh
#pragma pack(8) YM#XV*P0 q
)Cx8?\/c=x
struct s1{ (U-p&q>z
short a; \
fwf\&
long b; d8Upr1_
}; $\a;?>WA"
4N#0w]_,>Y
struct s2{ M2V.FYV{j>
char c; v[lytX4)
s1 d; 21cIWvy
long long e; mM}|x~\R
}; >A1Yn]k
D
Zh6/n#q
#pragma pack() /=Xen
mmS
+mxs jcq0
问 #0 ^QUOp
1.sizeof(s2) = ? /$q;-/DnTZ
2.s2的s1中的a后面空了几个字节接着是b? YQ?|Vb
U
gg8T],s1!a
W#??fae
%\-+SeC
如果您知道答案请在讨论中写出,以下是部份网友的答案,供参考: s]B^Sz=
-j<UhW
网友rwxybh(行云)的答案: ([$F5
q1TR
内存布局是 _I'O4s1S
1*** 11** ClfpA?vv
1111 **** ?xeq*<qfI
1111 1111 2TAy'BB;)
_q8s 7H
所以答案就是24和3 FtF!Dtv
r3*wH1n
下面是一个测试的程序,试一试就知道了,我用的是VC2005 7s[ ATu
NT8%{>F`
#pragma pack(8) gW*ee
^?juY}rZ=|
struct s1{ WUqAPN
short a; // 2 BYtes VUx~Y'b
long b; // 4 Bytes +)7NWR\
}; {0QA+[Yd&!
struct s2{ s)To#
char c; // 1 Byte zV2c`he%z
s1 d; // 8 Bytes T;FzKfT|
long long e; // 8 Bytes $9b||L
}; mCq*@1Lp9
// 1*** 11** 1,pg:=N9
// 1111 **** ?8~$du$
// 1111 1111 +ckj]yA;
// tv;3~Y0i
134wK]d^
// 00 01 02 03 04 05 06 07 i!Ne<Q
// 00 01 02 03 04 05 06 07 :z"Uw*
// 00 01 02 03 04 05 06 07 ZW\h,8%
// ^Xb!dnT.*a
#pragma pack() TZHqn6
MM5#B!BB
int main(int argc, char* argv[]) 1r.q]^Pq~
{ V];RQWs
s2 a; 1}'Jbj"/
char *p = (char *)&a; {+`ep\.$&
for(int i=0;i<24;++i) B!-W765Y
p = (char)(i%8); Bq2}nDP
printf("%d\n",sizeof(a)); vJcvyz#%1
printf("c=0x%lx\n",a.c); 6zNN 8
printf("d.a=0x%x\n",a.d.a); 8[y7(Xw
printf("d.b=0x%x\n",a.d.b); k} <mmKB
printf("e=0x%llx\n",a.e); 9(B)
return 0; 89 lPeFQ`
} .t}nznh
结果: lL83LhE}<
24 V5A7w
V3~
c=0x0 m1`ln5(R
d.a=0x504 P089Mh9
d.b=0x3020100 XBeHyQp
e=0x706050403020100 Gge"`AT
=|G PSRQ
:)MZgW
网友 redleaves (ID最吊的网友)的答案和分析: Ao]F_hZ
K+GjJ8
如果代码: B$lbp03z
#pragma pack(8) {wMCo,
struct S1{ &MKv_
char a; OrRve$U*|
long b; 0u0Hl% nl
}; E*'O))
struct S2 { t
Y^:C[
char c; ?pVODnP k
struct S1 d; w!xSYh')
long long e; nH_A`m3%/
}; f< '~K
#pragma pack() ; aMMIp
sizeof(S2)结果为24. BzgDhDj
成员对齐有一个重要的条件,即每个成员分别对齐.即每个成员按自己的方式对齐. */qv}
也就是说上面虽然指定了按8字节对齐,但并不是所有的成员都是以8字节对齐.其对齐的规则是,每个成员按其类型的对齐参数(通常是这个类型的大小)和指定对齐参数(这里是8字节)中较小的一个对齐.并且结构的长度必须为所用过的所有对齐参数的整数倍,不够就补空字节. K1C#
9PGSr4V1
S1中,成员a是1字节默认按1字节对齐,指定对齐参数为8,这两个值中取1,a按1字节对齐;成员b是4个字节,默认是按4字节对齐,这时就按4字节对齐,所以sizeof(S1)应该为8; ]IoS-)$Z/
S2中,c和S1中的a一样,按1字节对齐,而d 是个结构,它是8个字节,它按什么对齐呢?对于结构来说,它的默认对齐方式就是它的所有成员使用的对齐参数中最大的一个,S1的就是4.所以,成员d就是按4字节对齐.成员e是8个字节,它是默认按8字节对齐,和指定的一样,所以它对到8字节的边界上,这时,已经使用了12个字节了,所以又添加了4个字节的空,从第16个字节开始放置成员e.这时,长度为24,已经可以被8(成员e按8字节对齐)整除.这样,一共使用了24个字节. yC _X@o-n
a b 8,H
S1的内存布局:11**,1111, U}{r.MryFG
c S1.a S1.b d L'Wcb
=;
S2的内存布局:1***,11**,1111,****11111111 `rM-b'D
4sva%Up
这里有三点很重要: 7sFjO/a*
1.每个成员分别按自己的方式对齐,并能最小化长度 H-S28%.
2.复杂类型(如结构)的默认对齐方式是它最长的成员的对齐方式,这样在成员是复杂类型时,可以最小化长度 E]e6a^J#
3.对齐后的长度必须是成员中最大的对齐参数的整数倍,这样在处理数组时可以保证每一项都边界对齐 bZKK'd$I
\dCdyl6V
$QY(7Z"
网友xue23(xue23) 的答案和分析: +^%F8GB
{X<tUco
有程序查一下各个变量的内存地址得知: ;=E3f^'s
各个变量在内存中的位置为 KQ 2]VN"?_
c***aa** %f>V\z_C
bbbb**** hio{: (
dddddddd
"? R$9i
测试代码为: 6x.#K9@q4
s2 ss; B,A/
-B\
cout << "ss.c = " << &ss << endl ; ,iHl;3bu
cout << "ss.d.a = " <<&ss.d.a << endl; MbJV)*Q
cout << "ss.d.b = " <<&(ss.d.b) < cout << "ss.d = " <<&ss.e << endl; 3L;)asF
print out 各个变量的内存地址不就可以看出来了吗。 S3n$
|M+ !O93
所以答案是24,2. K~Xt`
q,m6$\g4
但是我的想像中应该是这样的分布情况: l~\'Z2op
c******* "rX`h
aa**bbbb k3e
$0`Q
dddddddd 8ayB<b>+]"
vk$]$6l2
不知为什么会c和a放在一起,组成8位长度。