Intel和微软同时出现的C语言面试题 :kgwKuhL
#pragma pack(8) iE$0-Qe[3
Hd4&"oeY
struct s1{ w^dB1Y7c(W
short a; @T1-0!TM')
long b; Q7i^VN
}; .NZ_dz$c
anv_I=
struct s2{ j'~xe3j
char c; N-lXC"{)
s1 d; >/Slk{
long long e; 1&wLNZXH
}; ^M8\ 3G
,)%nLc
#pragma pack() O(CUwk
,OG sx
问 sA:0b5_a
1.sizeof(s2) = ?
8DyE
2.s2的s1中的a后面空了几个字节接着是b? P oC*>R8
6D)
vY
DOf[? vbu
J/=b1{d"n
如果您知道答案请在讨论中写出,以下是部份网友的答案,供参考: . [*6W.X
~G,n>
网友rwxybh(行云)的答案: .DIHd/wA
内存布局是 o)srE5
1*** 11** *S`&
XPj
1111 **** 'lg6<M%#[
1111 1111 -&%#R_RV
kx*=1AfU+Y
所以答案就是24和3 ;IE|XR(
8+Oyhd*|
下面是一个测试的程序,试一试就知道了,我用的是VC2005 rWAJL9M
t d-EB&i\
#pragma pack(8) ,\xeNUZd
(?;Fnq
struct s1{
:p5V5iG
short a; // 2 BYtes XF'K dz>p
long b; // 4 Bytes Tgc)'8A;BN
}; m<hR
Lo
struct s2{ Sycs u_je
char c; // 1 Byte WR%x4\,d#
s1 d; // 8 Bytes S3A OT
long long e; // 8 Bytes eBlVb*nmq
}; TlQu+w|
// 1*** 11** #'_i6
// 1111 **** 1-Sc@WXd
// 1111 1111 R^{Ow
// "O!J6
mtOCk 5E
// 00 01 02 03 04 05 06 07 wspZ Eu>C;
// 00 01 02 03 04 05 06 07 M\ B A+
// 00 01 02 03 04 05 06 07 (ylpH`
// 049E#[<Q"
#pragma pack() #"jEc*&=
/n"Ib)M
int main(int argc, char* argv[]) tH`!?
{ }YfM<
s2 a; 0sD"Hu
char *p = (char *)&a; %ZDo;l+<F6
for(int i=0;i<24;++i) ]X ,f
p = (char)(i%8); 0R z'#O32V
printf("%d\n",sizeof(a)); pdUrVmW "'
printf("c=0x%lx\n",a.c); H.3+5po
printf("d.a=0x%x\n",a.d.a); :7
Ro9z8
printf("d.b=0x%x\n",a.d.b); 8!(4;fN$j.
printf("e=0x%llx\n",a.e); NifzZEX
return 0; ^rO3B?_
} 'Y Bz?l9
结果: 5xtIez]x?
24 z%Pbs[*C
c=0x0 v1*Lf/
d.a=0x504 Yx>y(Whu.
d.b=0x3020100 PQ9.aJdw@-
e=0x706050403020100 ?=}~]A5N
^@5#jS2
5v<X-8"
网友 redleaves (ID最吊的网友)的答案和分析: wH&[Tg
)GhMM
如果代码: {y-7xg~}
#pragma pack(8) + o^b ,!
struct S1{ _?$P?
char a; c
4xh
long b; /G[; kR"
}; &.~Xl:lq
struct S2 { b~uz\%'3
char c; i]oSVXx4WC
struct S1 d; rWzw7T~
long long e; vl+vzAd
}; WB~
^R<g
#pragma pack() DWT4D)C,U
sizeof(S2)结果为24. l;_zXN
成员对齐有一个重要的条件,即每个成员分别对齐.即每个成员按自己的方式对齐. yf5X=f.%@
也就是说上面虽然指定了按8字节对齐,但并不是所有的成员都是以8字节对齐.其对齐的规则是,每个成员按其类型的对齐参数(通常是这个类型的大小)和指定对齐参数(这里是8字节)中较小的一个对齐.并且结构的长度必须为所用过的所有对齐参数的整数倍,不够就补空字节. <7Igd6u
qo{2 CYG\+
S1中,成员a是1字节默认按1字节对齐,指定对齐参数为8,这两个值中取1,a按1字节对齐;成员b是4个字节,默认是按4字节对齐,这时就按4字节对齐,所以sizeof(S1)应该为8; 2\
3}y(
S2中,c和S1中的a一样,按1字节对齐,而d 是个结构,它是8个字节,它按什么对齐呢?对于结构来说,它的默认对齐方式就是它的所有成员使用的对齐参数中最大的一个,S1的就是4.所以,成员d就是按4字节对齐.成员e是8个字节,它是默认按8字节对齐,和指定的一样,所以它对到8字节的边界上,这时,已经使用了12个字节了,所以又添加了4个字节的空,从第16个字节开始放置成员e.这时,长度为24,已经可以被8(成员e按8字节对齐)整除.这样,一共使用了24个字节. LU
"e9
a b 57W4E{A
S1的内存布局:11**,1111, BfQRw>dZ"{
c S1.a S1.b d d9@!se9&Z
S2的内存布局:1***,11**,1111,****11111111 V0y Q
,jVj9m
这里有三点很重要: 1QkAFSl3
1.每个成员分别按自己的方式对齐,并能最小化长度 % heX06
2.复杂类型(如结构)的默认对齐方式是它最长的成员的对齐方式,这样在成员是复杂类型时,可以最小化长度 tu(k"'aJ
3.对齐后的长度必须是成员中最大的对齐参数的整数倍,这样在处理数组时可以保证每一项都边界对齐 n$>E'oG2t
57:Wh=x
dfkmIO%9X
网友xue23(xue23) 的答案和分析: 38(Cj~u=3
O}VI8OB(&
有程序查一下各个变量的内存地址得知: E*rnk4Y
各个变量在内存中的位置为 CH
h]v.V
c***aa** ,1>ABz
bbbb**** G}.t!"
dddddddd 4E&=qC]S
测试代码为: #)im9LLC#
s2 ss; GUUVE@Z
cout << "ss.c = " << &ss << endl ; "f'pa&oHi
cout << "ss.d.a = " <<&ss.d.a << endl; -t28"jyj
cout << "ss.d.b = " <<&(ss.d.b) < cout << "ss.d = " <<&ss.e << endl; tg%U2+.q
print out 各个变量的内存地址不就可以看出来了吗。 h9Zf4@w
7=jeq|&kN
所以答案是24,2. xv!
QO
mRIW9V
但是我的想像中应该是这样的分布情况: Yjo$^q
c******* 4BSSJ@z
aa**bbbb NG!~<Kx
dddddddd nr/^HjMV
\qPgQsy4
不知为什么会c和a放在一起,组成8位长度。