Intel和微软同时出现的C语言面试题 K_&MoyJJ9f
#pragma pack(8) H)(jh
Ey`h1Y
struct s1{ Gc,_v3\
short a; K|r Lkl9
long b; 5/0j}_pP
}; 1DJekiWf
!{%: qQiA
struct s2{ DXR:1w[^
char c; R9o- `Wz
s1 d; ,<Kx{+ [h
long long e; i@P}{
}; j? i#L}.I
S?0$? w?
#pragma pack() oF&l-DHp
,. EBOUW^
问 gFN9jM
1.sizeof(s2) = ? au@a8MP
2.s2的s1中的a后面空了几个字节接着是b? lCT{v@pp
/Lf6WMit
V"KS[>>f
:#t*K6dz
如果您知道答案请在讨论中写出,以下是部份网友的答案,供参考: *%FA:Y
7(a2L&k^
网友rwxybh(行云)的答案: j;~%lg=)
内存布局是 0\QR!*'$
1*** 11** nms8@[4-
1111 **** m_NCx]#e
1111 1111 EG<s_d?
8At<Wic
所以答案就是24和3 ]$iqa"{
3lxc4@Zmd
下面是一个测试的程序,试一试就知道了,我用的是VC2005 8{
c !).
o*S"KX$
#pragma pack(8) 5TKJWO.
OjE`1h\
struct s1{ wIvo"|%
short a; // 2 BYtes Vm1-C<V9
long b; // 4 Bytes A<MtKb
}; `)$_YZq|SR
struct s2{ VR?^HA9
char c; // 1 Byte e]8,:Gd(
s1 d; // 8 Bytes 7Ke&0eAw
long long e; // 8 Bytes Jf;?XP]z
}; ){;02^tX
// 1*** 11** kL*0M<0 (
// 1111 **** qdD)e$XW,
// 1111 1111 1OaXo!
// rSXzBi{
kAYb!h[`
// 00 01 02 03 04 05 06 07 B9dt=j3j2
// 00 01 02 03 04 05 06 07 GIwh@4;
// 00 01 02 03 04 05 06 07 8(U{2B8>\%
// ;3'NMk
#pragma pack() J>vMo@
<'U]`Lp
int main(int argc, char* argv[]) |UnUG
{ |bv,2uW z
s2 a; bCv {1]RC2
char *p = (char *)&a; E2wz(,@
for(int i=0;i<24;++i) n$L51#'
p = (char)(i%8); @ EuFJ=h
printf("%d\n",sizeof(a)); !0VfbY9C
printf("c=0x%lx\n",a.c); aBuoHdg;
printf("d.a=0x%x\n",a.d.a); V&{MQWy
printf("d.b=0x%x\n",a.d.b); rJyCw+N0
printf("e=0x%llx\n",a.e); >h~IfZU1
return 0; "f.Z}AbP
} IZ,oM!Y
结果: |,C#:"z;
24 uRV<?y%
c=0x0 Av J4\
d.a=0x504 S56]?M|[
d.b=0x3020100 "\%On >
e=0x706050403020100 %r{3wH#D@
mB'3N;~
jdA
]2]
网友 redleaves (ID最吊的网友)的答案和分析: sy* y\5yJ
\K2*Q&>
如果代码: uzOYVN$t
#pragma pack(8) Dh|w^Q
struct S1{ }GwVKAjP
char a; Ka!I`Yf
long b; W~n.Xeu{C
}; )$GIN/i
struct S2 { 5N$E()m$
char c; c7uG9
struct S1 d; ~"x5U{K48S
long long e; <!d"E@%v@
}; "8f?h%t
#pragma pack() j V3)2C}
sizeof(S2)结果为24. {lG@hN'
成员对齐有一个重要的条件,即每个成员分别对齐.即每个成员按自己的方式对齐. E$s/]wnr[
也就是说上面虽然指定了按8字节对齐,但并不是所有的成员都是以8字节对齐.其对齐的规则是,每个成员按其类型的对齐参数(通常是这个类型的大小)和指定对齐参数(这里是8字节)中较小的一个对齐.并且结构的长度必须为所用过的所有对齐参数的整数倍,不够就补空字节. kh$_!BT
#Il_J\#
S1中,成员a是1字节默认按1字节对齐,指定对齐参数为8,这两个值中取1,a按1字节对齐;成员b是4个字节,默认是按4字节对齐,这时就按4字节对齐,所以sizeof(S1)应该为8; PG%0yv%
S2中,c和S1中的a一样,按1字节对齐,而d 是个结构,它是8个字节,它按什么对齐呢?对于结构来说,它的默认对齐方式就是它的所有成员使用的对齐参数中最大的一个,S1的就是4.所以,成员d就是按4字节对齐.成员e是8个字节,它是默认按8字节对齐,和指定的一样,所以它对到8字节的边界上,这时,已经使用了12个字节了,所以又添加了4个字节的空,从第16个字节开始放置成员e.这时,长度为24,已经可以被8(成员e按8字节对齐)整除.这样,一共使用了24个字节. R{YzH56M
a b IXLO>>`
S1的内存布局:11**,1111, +FG$x/\*0
c S1.a S1.b d NcS.49
S2的内存布局:1***,11**,1111,****11111111 9' 1B/{
ff?t[GS
这里有三点很重要: Rg&-0b
1.每个成员分别按自己的方式对齐,并能最小化长度 .>g1$rj
2.复杂类型(如结构)的默认对齐方式是它最长的成员的对齐方式,这样在成员是复杂类型时,可以最小化长度 ,$*IzL~
3.对齐后的长度必须是成员中最大的对齐参数的整数倍,这样在处理数组时可以保证每一项都边界对齐 )EM7,xMz
eP1nUy=T
5/><$06rq
网友xue23(xue23) 的答案和分析: ^?"\?M1
cV
K7
有程序查一下各个变量的内存地址得知: 0rSIfYZa
各个变量在内存中的位置为 [4Ll0GSp
c***aa** {16<^
bbbb**** pE]?x$5U
dddddddd zSTR^sgJ
测试代码为: qeL pXe0c
s2 ss; +ZsX*/TOn
cout << "ss.c = " << &ss << endl ; Z$KLl((
cout << "ss.d.a = " <<&ss.d.a << endl; -!M,75nU
cout << "ss.d.b = " <<&(ss.d.b) < cout << "ss.d = " <<&ss.e << endl; R"Liz3Vl%
print out 各个变量的内存地址不就可以看出来了吗。 's?Ai2=#
Nt`b;X&
所以答案是24,2. S:Q! "U
>u+q1j.
但是我的想像中应该是这样的分布情况: UM%o\BiO
c******* 3k$[r$+"
aa**bbbb GV|9H]_,I
dddddddd 8ip7^
.Ce8L&