Intel和微软同时出现的C语言面试题 UK
OhsE
#pragma pack(8) dZ"}wKbO
1]>JMh%X9t
struct s1{ _9D]1f=&
short a; e3n^$'/\r
long b; &LM@xt4"^[
}; \ MuKS4
#HL$`&m
struct s2{ EE09 Er%\
char c; X,@nD@
s1 d; >#dLT~[\a
long long e; 3^Is4H_8
}; x=0Ak'1M
#}.{|'L
#pragma pack() k4&adX@Y
lYe2;bu
问 dDiy_Q6
1.sizeof(s2) = ? &pl)E$Y
2.s2的s1中的a后面空了几个字节接着是b? `Zp*?
(M;d*gNr
E_&;.hw
?p6@uM\Q7
如果您知道答案请在讨论中写出,以下是部份网友的答案,供参考: atZNX1LD[/
h_X'O3r
网友rwxybh(行云)的答案: no\G
>#
内存布局是 1V5N)ty
1*** 11** [*K9V/
1111 **** %dw0\:P?Q
1111 1111 8F\'?7
D7R;IA-w
所以答案就是24和3 %A
5s?J?
fC"?r6d
下面是一个测试的程序,试一试就知道了,我用的是VC2005 <> HI(6\@Z
gRs@T<k2
#pragma pack(8) %>nAPO+e
F6{
O
struct s1{ &: LE]w
short a; // 2 BYtes /W>?p@j+K
long b; // 4 Bytes ;t
N@
}; Lniz>gSc
struct s2{ ;U0w<>4L
char c; // 1 Byte J}Z\I Y,
s1 d; // 8 Bytes 0XE6Hw
long long e; // 8 Bytes JWu0VLo
}; Y)8 Py1}
// 1*** 11** =H-BsX?P
// 1111 **** Gf7r!Ur;g
// 1111 1111 3-y2i/4}$
// 0<-A2O),
|p/[sD+M
// 00 01 02 03 04 05 06 07 9-#=xE9'U
// 00 01 02 03 04 05 06 07 ty;a!yjC
// 00 01 02 03 04 05 06 07 !K.)Qr9 V
// @B)5Ho
#pragma pack() m{*_%tjN0
O~J f"Ht
int main(int argc, char* argv[]) UM1h[#?&V)
{ d|tNn@jN
s2 a; z\k6."e_&
char *p = (char *)&a; N#OO{`":Z`
for(int i=0;i<24;++i) $W;r S7b
p = (char)(i%8); 2e,cE6r
printf("%d\n",sizeof(a)); |em_l$oGc
printf("c=0x%lx\n",a.c); BN`tiPNEp
printf("d.a=0x%x\n",a.d.a); Zz|et206
printf("d.b=0x%x\n",a.d.b); }!kvoV)]1
printf("e=0x%llx\n",a.e); Yg!fEopLb
return 0; GOCe&?
} 6[Mu3.T
结果: Kr<a6BEv5
24 ;Uypv|xX
c=0x0 'eQ*?a43
d.a=0x504 %Q93n {?
d.b=0x3020100 Np
opg1Gv>
e=0x706050403020100 z9Y}[pN
:2t?0YR
:y~l?0b&8
网友 redleaves (ID最吊的网友)的答案和分析: nqYarHi
V[*<^%
如果代码: ~c,+)69"T
#pragma pack(8) ZB$,\|^6
struct S1{ \ 0F
ey9c
char a; sVS),9\}
long b; 1VXn`O?LW
}; ]|Iczg-
struct S2 { UN6nh T
char c; ;|vn;s/
struct S1 d; GQ9H>Ssz
long long e; )"bP]t^_
}; B%co`0$
#pragma pack() r+k~%5Ff~
sizeof(S2)结果为24. qaBL
成员对齐有一个重要的条件,即每个成员分别对齐.即每个成员按自己的方式对齐. ,Igd<A=
也就是说上面虽然指定了按8字节对齐,但并不是所有的成员都是以8字节对齐.其对齐的规则是,每个成员按其类型的对齐参数(通常是这个类型的大小)和指定对齐参数(这里是8字节)中较小的一个对齐.并且结构的长度必须为所用过的所有对齐参数的整数倍,不够就补空字节. Gd2t^tc
4n\O6$&.x
S1中,成员a是1字节默认按1字节对齐,指定对齐参数为8,这两个值中取1,a按1字节对齐;成员b是4个字节,默认是按4字节对齐,这时就按4字节对齐,所以sizeof(S1)应该为8; 8(@(G_skp
S2中,c和S1中的a一样,按1字节对齐,而d 是个结构,它是8个字节,它按什么对齐呢?对于结构来说,它的默认对齐方式就是它的所有成员使用的对齐参数中最大的一个,S1的就是4.所以,成员d就是按4字节对齐.成员e是8个字节,它是默认按8字节对齐,和指定的一样,所以它对到8字节的边界上,这时,已经使用了12个字节了,所以又添加了4个字节的空,从第16个字节开始放置成员e.这时,长度为24,已经可以被8(成员e按8字节对齐)整除.这样,一共使用了24个字节. \S#![NC
a b Q=498Y~x
S1的内存布局:11**,1111, ynq^ztBVe
c S1.a S1.b d $.Qq:(O:6
S2的内存布局:1***,11**,1111,****11111111 d?GB#N|+g
covK6SH
这里有三点很重要: y $>U[^G[
1.每个成员分别按自己的方式对齐,并能最小化长度 5F5)Bh
2.复杂类型(如结构)的默认对齐方式是它最长的成员的对齐方式,这样在成员是复杂类型时,可以最小化长度 Dv BRK}'
3.对齐后的长度必须是成员中最大的对齐参数的整数倍,这样在处理数组时可以保证每一项都边界对齐 dJ,,yA*
=eeZtj.
4^w`]m
网友xue23(xue23) 的答案和分析: QL@}hw.F
8Vm)jnM
有程序查一下各个变量的内存地址得知: 4V
5
各个变量在内存中的位置为 ?Hf8<C} 3
c***aa** x1.yi-
bbbb**** <QRRD*\
dddddddd JW=P}h
测试代码为: g/z7_Aq/
s2 ss; C1(0jUz
cout << "ss.c = " << &ss << endl ; J+nUxF;EE
cout << "ss.d.a = " <<&ss.d.a << endl; y}>bJ:
cout << "ss.d.b = " <<&(ss.d.b) < cout << "ss.d = " <<&ss.e << endl; !X{>?.@~
print out 各个变量的内存地址不就可以看出来了吗。 4q`e<!MP)q
,6T3:qkkvF
所以答案是24,2. U NescZ
U=KFbL1Q
但是我的想像中应该是这样的分布情况: X_J(P?
c******* $-BM`Zt0;
aa**bbbb }FAO.
dddddddd D]5cijO6
5uvFCY./c
不知为什么会c和a放在一起,组成8位长度。