Intel和微软同时出现的C语言面试题 V-go?b`
#pragma pack(8) x=7:D
B?-w<":!
struct s1{ %}zkmEY.e
short a; hR7uAk_?
long b; `4xQ#K.-
}; *aM7d>nG5
d;gs1]E50
struct s2{ PcT]
char c; Ym\<@[3+!
s1 d; G]k[A=dg
long long e; _,(s
}; 985h]KQ
j][&o-Ev
#pragma pack() H{5,
-x
WLj]EsA.
问 Fs4shrt
1.sizeof(s2) = ? 5,^DT15a4P
2.s2的s1中的a后面空了几个字节接着是b? +
<E
zv
XtZd%
#2},
`~=z0I
yeta)@nH
如果您知道答案请在讨论中写出,以下是部份网友的答案,供参考: K*DH_\SPK
3$YbEl@#
网友rwxybh(行云)的答案: L7(FDv,?
内存布局是 y_n4Y[4g
1*** 11** q\i&ERr
1111 **** (Ytr&gh;0
1111 1111 @#W4?L*D
EU:N9oT
所以答案就是24和3 0H4|}+e
\VOv&s;h
下面是一个测试的程序,试一试就知道了,我用的是VC2005 'do2n/
&)tv4L&
#pragma pack(8) u
e
4V,p\$;
struct s1{ !^MwE]
short a; // 2 BYtes ;Krs*3
s
long b; // 4 Bytes SODHn9)
}; J`[jub
struct s2{ pl@K"PRE
char c; // 1 Byte )ej1)RU"
s1 d; // 8 Bytes GQYn |vm
long long e; // 8 Bytes )_j(NX-C:
}; x5PM]~"p
// 1*** 11** N&
F.hi$_
// 1111 **** nTGf
// 1111 1111 {#?|&n<
// 0!%G#~th
[75?cQD
// 00 01 02 03 04 05 06 07 A*+gWn,4Y_
// 00 01 02 03 04 05 06 07 Y&,}q_Z:
// 00 01 02 03 04 05 06 07 X0j> g^b8
// %4M,f.[e
#pragma pack() =?y0fLTc
a;;
Es
int main(int argc, char* argv[]) lAo ~w
{
&gT@oS{
s2 a; ^4]=D nd%
char *p = (char *)&a; 5o4KV?"
for(int i=0;i<24;++i) <uFj5.
p = (char)(i%8); ->;2CcpHB
printf("%d\n",sizeof(a)); 7uw-1F5x7
printf("c=0x%lx\n",a.c); =IX-n$d`>
printf("d.a=0x%x\n",a.d.a); p]y.N)a
printf("d.b=0x%x\n",a.d.b); W58?t6!
=
printf("e=0x%llx\n",a.e); _(:$
:*@
return 0; H2[0@|<<
} E+<GsN]
结果: ~$^>Vo
24 |%XcI3@*
c=0x0 z8kebS&5
d.a=0x504 l\N2C4NG
d.b=0x3020100 -\%5aXr
e=0x706050403020100 eG2'W
,2FI?}+R
kQ&Q_FSO
网友 redleaves (ID最吊的网友)的答案和分析: vA6onYjA
=Sr<d|\O
如果代码: YE*|KL^
#pragma pack(8) 1K|F;p
struct S1{ ]3 GO_tL
char a; i-wWbZ-
long b; :}#)ipr
}; Qof%j@
struct S2 { !^NZp%Yd
char c; 1VG]|6f
struct S1 d; as/PM"
long long e; @U?&1.\
}; yXEI%2~)
#pragma pack() 2(\PsN w!
sizeof(S2)结果为24. Ax=)J{4v
成员对齐有一个重要的条件,即每个成员分别对齐.即每个成员按自己的方式对齐. G9jf]Ye;
也就是说上面虽然指定了按8字节对齐,但并不是所有的成员都是以8字节对齐.其对齐的规则是,每个成员按其类型的对齐参数(通常是这个类型的大小)和指定对齐参数(这里是8字节)中较小的一个对齐.并且结构的长度必须为所用过的所有对齐参数的整数倍,不够就补空字节. !or_CJ8%
z"QtP[_m
S1中,成员a是1字节默认按1字节对齐,指定对齐参数为8,这两个值中取1,a按1字节对齐;成员b是4个字节,默认是按4字节对齐,这时就按4字节对齐,所以sizeof(S1)应该为8; }Cfl|t<5f
S2中,c和S1中的a一样,按1字节对齐,而d 是个结构,它是8个字节,它按什么对齐呢?对于结构来说,它的默认对齐方式就是它的所有成员使用的对齐参数中最大的一个,S1的就是4.所以,成员d就是按4字节对齐.成员e是8个字节,它是默认按8字节对齐,和指定的一样,所以它对到8字节的边界上,这时,已经使用了12个字节了,所以又添加了4个字节的空,从第16个字节开始放置成员e.这时,长度为24,已经可以被8(成员e按8字节对齐)整除.这样,一共使用了24个字节. ]^wr+9zd
a b Jwj=a1I 53
S1的内存布局:11**,1111, }{,Wha5\n
c S1.a S1.b d D-i, C~W
S2的内存布局:1***,11**,1111,****11111111 y#`;[!
hHDLrr
这里有三点很重要: 3PLA*n+%
1.每个成员分别按自己的方式对齐,并能最小化长度 /d"@$+
2.复杂类型(如结构)的默认对齐方式是它最长的成员的对齐方式,这样在成员是复杂类型时,可以最小化长度 -nUK%a"(D
3.对齐后的长度必须是成员中最大的对齐参数的整数倍,这样在处理数组时可以保证每一项都边界对齐 P&[&Dj
;0 +Dx~
#^aa&*<D_
网友xue23(xue23) 的答案和分析: *""W`x
IW@phKz
有程序查一下各个变量的内存地址得知: ;P8%yf
各个变量在内存中的位置为 !OPHS^L
c***aa** Vom,^`}
bbbb**** `Z{s,!z
dddddddd q;sZwp<
测试代码为: C+`V?rp=s
s2 ss; >XiT[Ru
cout << "ss.c = " << &ss << endl ; -U9C{q?h
cout << "ss.d.a = " <<&ss.d.a << endl; 4!96k~d}
cout << "ss.d.b = " <<&(ss.d.b) < cout << "ss.d = " <<&ss.e << endl; ywyg(8>zE
print out 各个变量的内存地址不就可以看出来了吗。 D Vg$rm`
z`Nss
o=
所以答案是24,2. *6=9 8C4I
^k^?>h
但是我的想像中应该是这样的分布情况: yQ<h>J>
c******* <*u^8lCA
aa**bbbb IBu\Sh-
dddddddd fsnZHL}=n
Y8lZ]IB
不知为什么会c和a放在一起,组成8位长度。