Intel和微软同时出现的C语言面试题 ;'= cNj
#pragma pack(8) S!.sc
p2{7+m
struct s1{ .
yg#
short a; eY5mwJ0K
long b; |f#hGk6
}; b' y*\9Ru
G~YZ(+V%~
struct s2{ 'in%Gii
char c; N+rU|iMa.
s1 d; <78|~SKAV
long long e; D5D *$IC
}; K+F"V W*?
q!eE~O;A
#pragma pack() jk03 Hd
.4)oZ
问 8b)WOr6n
1.sizeof(s2) = ? Y \-W`
2.s2的s1中的a后面空了几个字节接着是b? jTvcKm|q
2Lf,~EV
:_~.Nt
L(VFzPkY%
如果您知道答案请在讨论中写出,以下是部份网友的答案,供参考: >+P}S@
<gkE,e9
网友rwxybh(行云)的答案: Yi*F;V
内存布局是 vSH,fS-n
1*** 11** Z~~6y6p
1111 **** 3R+%C* 7
1111 1111 b0{i +R
?<EzILM
所以答案就是24和3 h|CZ~
~oa}gJl:}-
下面是一个测试的程序,试一试就知道了,我用的是VC2005 wtY)(ka
g<W]NYm
#pragma pack(8) lFjz*g2'
&Q883A
J
struct s1{ H9/!oI1P?
short a; // 2 BYtes lFnls6dp
long b; // 4 Bytes |Ns4^2
}; pCs3-&rI3
struct s2{ H5}61 JC/z
char c; // 1 Byte }qn>#ETi
s1 d; // 8 Bytes .N X9Ab
long long e; // 8 Bytes fp' '+R[
}; ,|:.0g[n
// 1*** 11** WigtTAh4
// 1111 **** DM^0[3XuV5
// 1111 1111 mr\,"S-`
// JU?;Kq9R
d4S4
e
// 00 01 02 03 04 05 06 07 oMQ4q{&|
// 00 01 02 03 04 05 06 07 &n6{wtBP
// 00 01 02 03 04 05 06 07 "lh4Vg\7n
//
J=`
8
#pragma pack() tO M$'0u
;llPM`)
int main(int argc, char* argv[]) J3eud}w
{ 8;@y\0
s2 a; >n"0>[:4
char *p = (char *)&a; NnLK!Q
for(int i=0;i<24;++i) [ohLG_9
p = (char)(i%8); FS1\`#Bm)
printf("%d\n",sizeof(a)); 0cS$S Mn{
printf("c=0x%lx\n",a.c); U>2KjZB
printf("d.a=0x%x\n",a.d.a); 9 C[~*,qx
printf("d.b=0x%x\n",a.d.b); (U:-z=E#1
printf("e=0x%llx\n",a.e); I%5vI}
return 0; t*IePz] /
} Lh[0B.g<
结果: u cpU$+
24 w2
Y%yjCV
c=0x0 DBAyc#
d.a=0x504 Hr?lRaV
d.b=0x3020100 A8'RM F1
e=0x706050403020100 ^Arv6kD,
>+M[!;m}
?b]zsku8
网友 redleaves (ID最吊的网友)的答案和分析: 4 Ej->T.
<?.eU<+O`S
如果代码: gi!_Nz
#pragma pack(8) /vSGmW-*
struct S1{ Wk%|%/:
char a; v"k ?e
long b; D6bYg `
}; N~!,
S;w
struct S2 { KuJ)alD;1
char c; *tqD:hiF
struct S1 d; XoKgs, y4
long long e; \?n6l7*t>
}; cGV%=N^BE<
#pragma pack() XDPR$u8hM
sizeof(S2)结果为24. M/o?D <'
成员对齐有一个重要的条件,即每个成员分别对齐.即每个成员按自己的方式对齐. 7KIekL
也就是说上面虽然指定了按8字节对齐,但并不是所有的成员都是以8字节对齐.其对齐的规则是,每个成员按其类型的对齐参数(通常是这个类型的大小)和指定对齐参数(这里是8字节)中较小的一个对齐.并且结构的长度必须为所用过的所有对齐参数的整数倍,不够就补空字节. 5M5Bm[X
_lv{ 8vf1B
S1中,成员a是1字节默认按1字节对齐,指定对齐参数为8,这两个值中取1,a按1字节对齐;成员b是4个字节,默认是按4字节对齐,这时就按4字节对齐,所以sizeof(S1)应该为8; 8jz>^.-o
S2中,c和S1中的a一样,按1字节对齐,而d 是个结构,它是8个字节,它按什么对齐呢?对于结构来说,它的默认对齐方式就是它的所有成员使用的对齐参数中最大的一个,S1的就是4.所以,成员d就是按4字节对齐.成员e是8个字节,它是默认按8字节对齐,和指定的一样,所以它对到8字节的边界上,这时,已经使用了12个字节了,所以又添加了4个字节的空,从第16个字节开始放置成员e.这时,长度为24,已经可以被8(成员e按8字节对齐)整除.这样,一共使用了24个字节. g{N}]_%Uh
a b ?}?"m:=
S1的内存布局:11**,1111, Ow;thNN
c S1.a S1.b d KU8,8:yY
S2的内存布局:1***,11**,1111,****11111111 SJiQg-+<Uf
$mJv\;t
这里有三点很重要: w9|x{B
1.每个成员分别按自己的方式对齐,并能最小化长度 }b1G21Dc!
2.复杂类型(如结构)的默认对齐方式是它最长的成员的对齐方式,这样在成员是复杂类型时,可以最小化长度 7i" b\{5
3.对齐后的长度必须是成员中最大的对齐参数的整数倍,这样在处理数组时可以保证每一项都边界对齐 (.#nl}fA
AS;Sz/YP
p-s\D_
网友xue23(xue23) 的答案和分析: >w.;A%|N
:ts3_-cr
有程序查一下各个变量的内存地址得知: x;?8Zr
各个变量在内存中的位置为 6:8s,a3&[k
c***aa** j@4MV^F2c
bbbb**** cW*v))@2
dddddddd B{/og*xd*1
测试代码为: f-M:ap(O
s2 ss; gKb,Vrt
cout << "ss.c = " << &ss << endl ; b+~_/;Y9
cout << "ss.d.a = " <<&ss.d.a << endl; f\R_a/Us
cout << "ss.d.b = " <<&(ss.d.b) < cout << "ss.d = " <<&ss.e << endl; sK#)k\w>
print out 各个变量的内存地址不就可以看出来了吗。 Z
)c\B
^SpQtW118
所以答案是24,2.
}ktIG|GC
D9+qT<ojN
但是我的想像中应该是这样的分布情况: ZLzc\>QX
c******* [63\2{_^v
aa**bbbb 4. R(`#f
dddddddd ,&BNN]k
+2iD9X{$MX
不知为什么会c和a放在一起,组成8位长度。