Intel和微软同时出现的C语言面试题 %awVVt{aG
#pragma pack(8) mHHzCKE ,
s1Okoxh/!V
struct s1{ OFIMi^@
short a; LjC6?a_?l
long b; n3*UgNg%fK
}; >j)
w\i
;{]8>`im&4
struct s2{
rWqkdi1
char c; 2mSD"[%
s1 d; >"O1`xdG
long long e; |&Au6 3
}; TMNfJz
zfirb
#pragma pack() n'ehB%"
[h^f%
问 \U Ax(;
1.sizeof(s2) = ? 6{ C Fe|XN
2.s2的s1中的a后面空了几个字节接着是b? l`G(O$ct
w/O<.8+
erXy>H[;
'HJ/2-=
如果您知道答案请在讨论中写出,以下是部份网友的答案,供参考: *$JB`=Q
t18UDR{
网友rwxybh(行云)的答案: ~~U<
内存布局是 6#fOCr;f7
1*** 11** ,zG <7~m
1111 **** 8znj~7}#
1111 1111 A"0wvk)UcY
(eki X*y
所以答案就是24和3 >H)^6sJ;%b
yB=C5-\F
下面是一个测试的程序,试一试就知道了,我用的是VC2005 u>81dO]H
xJN |w\&
#pragma pack(8) iwB8I^
>kt~vJI
struct s1{ {ip=iiW2
short a; // 2 BYtes >6XDX=JVI
long b; // 4 Bytes )-)ss"\+Ju
}; Fgskb"k/
struct s2{ - J{Dxz
char c; // 1 Byte vJ~4D*(]l
s1 d; // 8 Bytes N4A&"1d&
long long e; // 8 Bytes Sy4
mZ}:
}; )\D2\1e(c
// 1*** 11** dFx2>6AZt
// 1111 **** @X
K>
// 1111 1111 N?\bBt@
// nG!&u1*
A S`2=w
// 00 01 02 03 04 05 06 07 lt{lHat1
// 00 01 02 03 04 05 06 07 `i=JjgG@
// 00 01 02 03 04 05 06 07 h -Tsi:%b
// =d}gv6v2S
#pragma pack() ^WmGo]<B_
\5t`p67Ve_
int main(int argc, char* argv[]) V+peO
{ Xg,0 /P~
s2 a; U?JiVxE^
char *p = (char *)&a; n?zbUA#
for(int i=0;i<24;++i) (D0C#<4P
p = (char)(i%8); 7U&5^s
)J
printf("%d\n",sizeof(a)); &fCP2]hj'
printf("c=0x%lx\n",a.c); U~oBNsU"
printf("d.a=0x%x\n",a.d.a); >_&~!Y.Z=
printf("d.b=0x%x\n",a.d.b); J 5Wz4`'
printf("e=0x%llx\n",a.e); j?Cr31
return 0; RP,A!pa@
} |sA4:Aq
结果: @c6"RHG9
24 zv$Gma_
c=0x0 m$7x#8gF
d.a=0x504 +fC#2%VnU
d.b=0x3020100 /_$~rW
e=0x706050403020100 L@>^_p$
aUKh})B
9BqQ^`bu
网友 redleaves (ID最吊的网友)的答案和分析: 7bA4P*
AF6d#Klog
如果代码: dNOX&$/=
#pragma pack(8) ls [Ls
struct S1{ N8,EI^W8Z
char a; X!,#'&p&
long b; x1 .3W j
}; nw~/~eM5=
struct S2 { ;%BhhmR)[
char c; O3_D~O
."
struct S1 d; _L?v6MTj
long long e; b ^uP^](J
}; <^CYxy
#pragma pack() I++W0wa.n
sizeof(S2)结果为24. xIS\4]F?r
成员对齐有一个重要的条件,即每个成员分别对齐.即每个成员按自己的方式对齐. z0T`5NG@
也就是说上面虽然指定了按8字节对齐,但并不是所有的成员都是以8字节对齐.其对齐的规则是,每个成员按其类型的对齐参数(通常是这个类型的大小)和指定对齐参数(这里是8字节)中较小的一个对齐.并且结构的长度必须为所用过的所有对齐参数的整数倍,不够就补空字节. @PT`CK}
qgwv=5|
S1中,成员a是1字节默认按1字节对齐,指定对齐参数为8,这两个值中取1,a按1字节对齐;成员b是4个字节,默认是按4字节对齐,这时就按4字节对齐,所以sizeof(S1)应该为8; "V*kOb&'*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个字节. 8|w5QvCU?3
a b ZmEG<T05
S1的内存布局:11**,1111, aSn0o_4bD
c S1.a S1.b d (:_%kmu
S2的内存布局:1***,11**,1111,****11111111 M3DxapG
?l6>6a7
这里有三点很重要: W2}%zux
1.每个成员分别按自己的方式对齐,并能最小化长度 08zi/g2
3
2.复杂类型(如结构)的默认对齐方式是它最长的成员的对齐方式,这样在成员是复杂类型时,可以最小化长度 @/CRIei
3.对齐后的长度必须是成员中最大的对齐参数的整数倍,这样在处理数组时可以保证每一项都边界对齐 C_;HaQiu
OT-n\sL$
RY\{=f
网友xue23(xue23) 的答案和分析: KU1+<OCh
80{#bb
有程序查一下各个变量的内存地址得知: K)yCrEZ
各个变量在内存中的位置为 "WF(
6z#
c***aa** GCcwEl!K^
bbbb**** iifc;6 2
dddddddd a"`g"ZRx
测试代码为: ) 1lJ<g#
s2 ss; Iq4 Kgc
cout << "ss.c = " << &ss << endl ; 4?9soc
cout << "ss.d.a = " <<&ss.d.a << endl; UI|v/(_^F
cout << "ss.d.b = " <<&(ss.d.b) < cout << "ss.d = " <<&ss.e << endl; 03X<x|
print out 各个变量的内存地址不就可以看出来了吗。 "\VW.S
t`
}20=I+
所以答案是24,2. 9F2w.(m
k)H[XpM
但是我的想像中应该是这样的分布情况: v+xgxQGYH
c******* K!IF?iell
aa**bbbb hKk\Y{wv'
dddddddd * 23m-
1_Dn?G^H
不知为什么会c和a放在一起,组成8位长度。