Intel和微软同时出现的C语言面试题 [uGsF0#e
#pragma pack(8) f8[O]MrO;
)bih>>H
struct s1{ @@^iN~uf
short a; p~3x=X4
long b; 9tv,,I;iU
}; /d}"s.3p
, d $"`W2
struct s2{ d'Bxi"K
char c; aL[6}U0 (}
s1 d; UH6 7<_mK
long long e; ?e6>dNw
}; 2?
yo
`XH0S`B
#pragma pack() O<Q8%Az
r!fUMDS
问 vVSDPlN;
1.sizeof(s2) = ? r@C~_LgL)
2.s2的s1中的a后面空了几个字节接着是b? iii|;v]+
=q]!"yU[d
mj$Ucql
/;(ji?wN
如果您知道答案请在讨论中写出,以下是部份网友的答案,供参考: nl
'MWP
v.<mrI#?
网友rwxybh(行云)的答案: hT 1JEu
内存布局是 FfM^2`xP
1*** 11** MZ$uWm`/
1111 **** 5C1EdQ4S0
1111 1111 Wgh@X B
WtZI1`\qe
所以答案就是24和3 \mh #MMp
5z0VMt
下面是一个测试的程序,试一试就知道了,我用的是VC2005 G`n
$A/9Q
-O\i^?lD;
#pragma pack(8) TyIjDG6tM
Rs5 lL-I
struct s1{ \X&8EW
short a; // 2 BYtes % Q6
za'25
long b; // 4 Bytes ?[Y(JO#
}; Y&yfm/R u
struct s2{ M\4`S&
char c; // 1 Byte @~$"&B
s1 d; // 8 Bytes t?G6|3
long long e; // 8 Bytes 2lsUCQI;
}; Sp X;nH-D
// 1*** 11** aA#79LS
// 1111 **** {,sqUq (
// 1111 1111 AcuF0KWw/
// tjFX(;^[
B
}%2FUv
// 00 01 02 03 04 05 06 07 ~C%I'z'
// 00 01 02 03 04 05 06 07 nI]EfHU
// 00 01 02 03 04 05 06 07 :1UMA@HP
// 8lpAe0p(Z
#pragma pack() O_1[KiZ
X8ap
int main(int argc, char* argv[]) b v_UroTr
{ j~{cT/5Y_
s2 a; HQm_ K0$
char *p = (char *)&a; ?MRY*[$
for(int i=0;i<24;++i) U&WEe`XM
p = (char)(i%8); -%"PqA/1zj
printf("%d\n",sizeof(a)); V_gKl;Kfe8
printf("c=0x%lx\n",a.c); cw!,.o%cD
printf("d.a=0x%x\n",a.d.a); =J]WVA,GqA
printf("d.b=0x%x\n",a.d.b); DBHy%i
printf("e=0x%llx\n",a.e); {7goYzQsi%
return 0; To>,8E+GAb
} oV:oc,
结果: D;C';O
24 XJe=+_K9
c=0x0 ffmtTJFC5
d.a=0x504 eo9/
d.b=0x3020100 ~I5hV}ZT
e=0x706050403020100 ~)ys,Q
m@Yc&M~
\i_E}Ii0
网友 redleaves (ID最吊的网友)的答案和分析: .^{%hc*w4
O,B\|pd2
如果代码: 95mf
#pragma pack(8) j-ej7
struct S1{ -n05Z@7
char a; C*(
long b; GV Xdyi
}; AChz}N$C
struct S2 { |2q3spd
char c; AVpg
struct S1 d; ]Orx%8QS!
long long e; d>hv-nD
}; g.Xk6"kO
#pragma pack() %)r ~GCd
sizeof(S2)结果为24. r+FEgSDa]
成员对齐有一个重要的条件,即每个成员分别对齐.即每个成员按自己的方式对齐. /J#(8p
也就是说上面虽然指定了按8字节对齐,但并不是所有的成员都是以8字节对齐.其对齐的规则是,每个成员按其类型的对齐参数(通常是这个类型的大小)和指定对齐参数(这里是8字节)中较小的一个对齐.并且结构的长度必须为所用过的所有对齐参数的整数倍,不够就补空字节. \A[l(aB
kCTf>sJe
S1中,成员a是1字节默认按1字节对齐,指定对齐参数为8,这两个值中取1,a按1字节对齐;成员b是4个字节,默认是按4字节对齐,这时就按4字节对齐,所以sizeof(S1)应该为8; w95M
B*N
S2中,c和S1中的a一样,按1字节对齐,而d 是个结构,它是8个字节,它按什么对齐呢?对于结构来说,它的默认对齐方式就是它的所有成员使用的对齐参数中最大的一个,S1的就是4.所以,成员d就是按4字节对齐.成员e是8个字节,它是默认按8字节对齐,和指定的一样,所以它对到8字节的边界上,这时,已经使用了12个字节了,所以又添加了4个字节的空,从第16个字节开始放置成员e.这时,长度为24,已经可以被8(成员e按8字节对齐)整除.这样,一共使用了24个字节. uMg\s\Z
a b d5m-f/
S1的内存布局:11**,1111, k|)fl l
c S1.a S1.b d tz@MZs09
S2的内存布局:1***,11**,1111,****11111111 k3#'g'>yh
0ae8Xm3J@R
这里有三点很重要: Q>%n&;:
1.每个成员分别按自己的方式对齐,并能最小化长度 +%W8Juu
2.复杂类型(如结构)的默认对齐方式是它最长的成员的对齐方式,这样在成员是复杂类型时,可以最小化长度 5X!-Hj
3.对齐后的长度必须是成员中最大的对齐参数的整数倍,这样在处理数组时可以保证每一项都边界对齐 _!',%+
C.jWT1
&j4pC$Dj
网友xue23(xue23) 的答案和分析: )Zr9
`3[
=hKAwk/^
有程序查一下各个变量的内存地址得知: rR.It,,
各个变量在内存中的位置为 B'}?cG]
c***aa** p)IL(_X)
bbbb**** y>a?<*Y+e
dddddddd y'_8b=*
测试代码为: Ym6d'd<9(
s2 ss; {.:$F3T
cout << "ss.c = " << &ss << endl ; q?(]
Y*
cout << "ss.d.a = " <<&ss.d.a << endl; Y b+A{`
cout << "ss.d.b = " <<&(ss.d.b) < cout << "ss.d = " <<&ss.e << endl; OT{"C"%5t
print out 各个变量的内存地址不就可以看出来了吗。 *1dDs^D#|
D!&(#Vl
_
所以答案是24,2. P"vrYom
3xChik{
但是我的想像中应该是这样的分布情况: A;TP~xq\
c******* Nwi|>'\C
aa**bbbb yn62NyK
dddddddd &P?2H66s
j<<d A[X
不知为什么会c和a放在一起,组成8位长度。