Intel和微软同时出现的C语言面试题 V+8+ 17^
#pragma pack(8) r
{8
W6PGv1iaW>
struct s1{ hi=U
short a; ?( '%QfT
long b; e`oc#Od&x]
}; KV6S-
`7j,njCX.
struct s2{ gu/Yc`S[
char c; aJF`rLm
s1 d; |WX4L7yrhK
long long e; ob;oxJ@[c
}; %(]rc%ry0
<(^pHv7Q
#pragma pack()
,i|f8pZ
e,BJD>N ?
问 G pd:k
1.sizeof(s2) = ? ;CW$/^QNr5
2.s2的s1中的a后面空了几个字节接着是b? )Ga6O2:
|j+~Td3})&
ieI-_]|[
H~@h
#6
如果您知道答案请在讨论中写出,以下是部份网友的答案,供参考: WIghP5% W
NWvxbv
网友rwxybh(行云)的答案: 2V]2jxOQ
内存布局是 W1s|7
1*** 11** s,RS}ek~|
1111 **** 3:gk:j#
1111 1111 5Zov<+kE
1K`A.J:Uy
所以答案就是24和3 AM[:Og S
4L0LT>'M\
下面是一个测试的程序,试一试就知道了,我用的是VC2005 c"xaN
pI`Ke"
#pragma pack(8) ,?qS#B+>
"xOeBNRjV
struct s1{
Ojs\2('u
short a; // 2 BYtes L:<'TXsRA
long b; // 4 Bytes ke0W?
}; D8ly8]H
struct s2{ .EdV36$n
char c; // 1 Byte _=MWt_A '3
s1 d; // 8 Bytes hD*?\bBs0
long long e; // 8 Bytes F)@<ZE
}; 9V&LJhDQ
// 1*** 11** UO wNcY
// 1111 **** #q- _
// 1111 1111 <wC1+/]
// UQFuEI<1-
DXt^Ym5Cv
// 00 01 02 03 04 05 06 07 (0+m&,
z
// 00 01 02 03 04 05 06 07 `g=~u{0
// 00 01 02 03 04 05 06 07 *pMA
V[^
// #5D+XB T
#pragma pack() DkIFvsLK
9E^piLA
int main(int argc, char* argv[]) Ba6xkEd
{ UU/|s>F
s2 a; 4pqZ!@45|
char *p = (char *)&a; AMdS+(J
for(int i=0;i<24;++i) hs4r5[
p = (char)(i%8); *C BCQp[$
printf("%d\n",sizeof(a)); 7h2bL6Y88
printf("c=0x%lx\n",a.c); <c#[.{A}s
printf("d.a=0x%x\n",a.d.a); zCrcCr
printf("d.b=0x%x\n",a.d.b); YO,ldsSz|r
printf("e=0x%llx\n",a.e); W}RR_Gu
return 0; *QG;KJ%
} s<b7/;w'
结果: @-}]~|<
24 brWt
c=0x0 =S,<yQJ
d.a=0x504 9o`3g@6z
d.b=0x3020100 7 SZR#L
e=0x706050403020100 :+Kesa:E
WQx;tX
9x!y.gx
网友 redleaves (ID最吊的网友)的答案和分析: _SqrQ
9[D7N
如果代码: YC'~8\x3z
#pragma pack(8) @Hh"Y1B
struct S1{ B}X#oA
char a; e=jO_[
long b; 5MJ'/Fy(
}; "puz-W'n
struct S2 { AHGcWS\,X
char c; R{vPn8X6g
struct S1 d; 8H?AL
RG
long long e; B5G$o{WM
}; }^7V^W
#pragma pack() /3]|B%W9
sizeof(S2)结果为24. 3)Y:c2
成员对齐有一个重要的条件,即每个成员分别对齐.即每个成员按自己的方式对齐. <.ky1aex7
也就是说上面虽然指定了按8字节对齐,但并不是所有的成员都是以8字节对齐.其对齐的规则是,每个成员按其类型的对齐参数(通常是这个类型的大小)和指定对齐参数(这里是8字节)中较小的一个对齐.并且结构的长度必须为所用过的所有对齐参数的整数倍,不够就补空字节. {9
O`/|
+b W|Q>u
S1中,成员a是1字节默认按1字节对齐,指定对齐参数为8,这两个值中取1,a按1字节对齐;成员b是4个字节,默认是按4字节对齐,这时就按4字节对齐,所以sizeof(S1)应该为8; @_3$(*n$~
S2中,c和S1中的a一样,按1字节对齐,而d 是个结构,它是8个字节,它按什么对齐呢?对于结构来说,它的默认对齐方式就是它的所有成员使用的对齐参数中最大的一个,S1的就是4.所以,成员d就是按4字节对齐.成员e是8个字节,它是默认按8字节对齐,和指定的一样,所以它对到8字节的边界上,这时,已经使用了12个字节了,所以又添加了4个字节的空,从第16个字节开始放置成员e.这时,长度为24,已经可以被8(成员e按8字节对齐)整除.这样,一共使用了24个字节. x(=x;X$[^
a b cmI#R1\
S1的内存布局:11**,1111, ub5hX{uT
c S1.a S1.b d Hea<!zPH
S2的内存布局:1***,11**,1111,****11111111 ?C35
;kBies>V
这里有三点很重要: `@7tWX0
1.每个成员分别按自己的方式对齐,并能最小化长度 03@|dN
2.复杂类型(如结构)的默认对齐方式是它最长的成员的对齐方式,这样在成员是复杂类型时,可以最小化长度 t;Om9
3.对齐后的长度必须是成员中最大的对齐参数的整数倍,这样在处理数组时可以保证每一项都边界对齐 Z >=Y
,6"n5Ks}
98^6{p
网友xue23(xue23) 的答案和分析: "'Uk0>d=_I
B:cOcd?p
有程序查一下各个变量的内存地址得知: fx:KH:q3
各个变量在内存中的位置为 (N4(r<o;
c***aa** 'OCo1|iK~
bbbb**** ->=++
dddddddd J-F_XKqH
测试代码为: kB#vh
s2 ss; bl_WN|SQ
cout << "ss.c = " << &ss << endl ; ^ {f^WL=
cout << "ss.d.a = " <<&ss.d.a << endl; VhgEG(Ud
cout << "ss.d.b = " <<&(ss.d.b) < cout << "ss.d = " <<&ss.e << endl; WmUW
i{
print out 各个变量的内存地址不就可以看出来了吗。 A#&qoZ(C
D|9fHMg%
所以答案是24,2. #Ca's'j&f
Q%Q?q)x
但是我的想像中应该是这样的分布情况: 3:lp"C51
c******* nD\os[ 3
aa**bbbb [dlH
t;S
dddddddd .N&}<T[
_9|@nUD
不知为什么会c和a放在一起,组成8位长度。