Intel和微软同时出现的C语言面试题 J5;5-:N
#pragma pack(8) 88
{1mA,v
4AQ[igTDP
struct s1{ XlVc\?
short a; "lTZ|k^
long b; 0mTEim
}; ?KCivf
:V-k'hm
&
struct s2{ U2bzUxK
char c; <|a=hHPi:
s1 d; IhE9snJ[
long long e; s
D_G)c
};
rIVvO
'@bJlJB9>
#pragma pack() ?mMW*ico
fYB*6Xb,w
问 'G8 ?'u_)
1.sizeof(s2) = ? {SJsA)9:#
2.s2的s1中的a后面空了几个字节接着是b? 1fY>>*oP
b0 &
?W!ry7gXO
m2(E>raV6
如果您知道答案请在讨论中写出,以下是部份网友的答案,供参考: eRs&iK2y
`a
>?UUT4
网友rwxybh(行云)的答案: Me,<\rQ
内存布局是 0Gsu
1*** 11** Jt]&;0zn2
1111 **** 4z_n4=
1111 1111 w>[T&0-N
e[{mVhg4E
所以答案就是24和3 fagM7)x
rLzW`
下面是一个测试的程序,试一试就知道了,我用的是VC2005 k][h9'
g*y/j]
#pragma pack(8) 59<hV?
tuLH}tkNY
struct s1{ ARF\fF|<2
short a; // 2 BYtes qSTW b%
long b; // 4 Bytes >b48>@~bY
}; c<4F4k7
struct s2{ mb1Vu
char c; // 1 Byte CxDcY
s1 d; // 8 Bytes ?#BV+#(
long long e; // 8 Bytes AbfZ++aJ
}; =K(JqSw+M
// 1*** 11** Vb!O8xV4;+
// 1111 **** E^wyD-ii/
// 1111 1111 aQUGNa0+d
// dZ]Rqr
_!
VEs5;]#<2D
// 00 01 02 03 04 05 06 07 "3}<8c
// 00 01 02 03 04 05 06 07 g^l RG3a
// 00 01 02 03 04 05 06 07 vtyx`F
f
// %>zjGF<
#pragma pack() wL3,g2- L
SK
R1E];4
int main(int argc, char* argv[]) {^m Kvc
{ }mk>!B}=
s2 a; `}fw1X5L
char *p = (char *)&a; BBnq_w"a
for(int i=0;i<24;++i) A@$kLex
p = (char)(i%8); "9XfQ"P
printf("%d\n",sizeof(a)); (=c1
printf("c=0x%lx\n",a.c); vzXag*0
printf("d.a=0x%x\n",a.d.a); .H~YI
printf("d.b=0x%x\n",a.d.b); Ri)uq\E/#
printf("e=0x%llx\n",a.e); fS=hpL6]@
return 0; |"]PCb)!
} QyGnDomQ
结果: 80;n|nNB
24 (9C<K<
c=0x0 jc:s` 4
d.a=0x504 F)Oe9x\/
d.b=0x3020100 lzhqcL"
e=0x706050403020100 :P+\p=
C6
"
"G?Yrh
网友 redleaves (ID最吊的网友)的答案和分析: Q(Gl{#b
gfg n68k
如果代码: x#H
3=YD*
#pragma pack(8) :/N+;- 18
struct S1{ ,S&z<S_
char a; 09h.1/
long b; L'Q<>{;Ig
}; 1G^#q,%X_v
struct S2 { |E)aT#$f'
char c; Log|%P\
struct S1 d; -{jdn%Y7CK
long long e; 9`B$V##-L
}; 7cTk@Gq
#pragma pack() ;zH
HIdQ>-
sizeof(S2)结果为24. Jn&7C
成员对齐有一个重要的条件,即每个成员分别对齐.即每个成员按自己的方式对齐. Jkt4@h2Q}
也就是说上面虽然指定了按8字节对齐,但并不是所有的成员都是以8字节对齐.其对齐的规则是,每个成员按其类型的对齐参数(通常是这个类型的大小)和指定对齐参数(这里是8字节)中较小的一个对齐.并且结构的长度必须为所用过的所有对齐参数的整数倍,不够就补空字节. 7h9U{4r: M
)>a B
S1中,成员a是1字节默认按1字节对齐,指定对齐参数为8,这两个值中取1,a按1字节对齐;成员b是4个字节,默认是按4字节对齐,这时就按4字节对齐,所以sizeof(S1)应该为8; 1;F`c`0<
S2中,c和S1中的a一样,按1字节对齐,而d 是个结构,它是8个字节,它按什么对齐呢?对于结构来说,它的默认对齐方式就是它的所有成员使用的对齐参数中最大的一个,S1的就是4.所以,成员d就是按4字节对齐.成员e是8个字节,它是默认按8字节对齐,和指定的一样,所以它对到8字节的边界上,这时,已经使用了12个字节了,所以又添加了4个字节的空,从第16个字节开始放置成员e.这时,长度为24,已经可以被8(成员e按8字节对齐)整除.这样,一共使用了24个字节. ~d
>W?A
a b 7'lZg<z{~j
S1的内存布局:11**,1111, qxOi>v0\H
c S1.a S1.b d 0JjUAxNq
S2的内存布局:1***,11**,1111,****11111111 R[B?C;+(O
z@ 35NZn
这里有三点很重要: 60>.ul2
1.每个成员分别按自己的方式对齐,并能最小化长度 *%5{'
2.复杂类型(如结构)的默认对齐方式是它最长的成员的对齐方式,这样在成员是复杂类型时,可以最小化长度 6<76H
3.对齐后的长度必须是成员中最大的对齐参数的整数倍,这样在处理数组时可以保证每一项都边界对齐 /~p+j{0L3W
mN_Z7n;^eh
q(M:QWA q
网友xue23(xue23) 的答案和分析: x.mrCJn)
A!i q->+
有程序查一下各个变量的内存地址得知: @OpNHQat9
各个变量在内存中的位置为 zg)sd1@
c***aa** jNDx,7F-
bbbb**** V@-)\RZm
dddddddd f .
}c7
测试代码为: <If35Z)~
s2 ss; #U
mF-c
cout << "ss.c = " << &ss << endl ; w8Sv*K
cout << "ss.d.a = " <<&ss.d.a << endl; 8hanzwoJ:
cout << "ss.d.b = " <<&(ss.d.b) < cout << "ss.d = " <<&ss.e << endl; EbNd=Z'J
print out 各个变量的内存地址不就可以看出来了吗。 BqK(DH^9N
$FTO
所以答案是24,2. ;E^K.6
tz NlJ~E
但是我的想像中应该是这样的分布情况: e.d
#wyeX
c******* ,MPB/j^o5!
aa**bbbb w*9br SK
dddddddd K$ }a8rH
"UFs~S|e
不知为什么会c和a放在一起,组成8位长度。