Intel和微软同时出现的C语言面试题 )W/;=K
#pragma pack(8) X 1
57$
okbQ<{9
struct s1{ p
w8 s8?
short a; ,) J~ ,^f6
long b; 9IX/wm"
}; lXcx@#~
3EJt%}V$k
struct s2{ :VTTh
|E%#
char c; ns6(cJ^a
s1 d; xJ#d1[kzo
long long e; ;4Y%PVz~D
}; SkmT`*v@
:POj6j/
#pragma pack() ^0/j0]O
;L']e"G
问 CrwwU7qKL
1.sizeof(s2) = ? 5[c^TJ3
2.s2的s1中的a后面空了几个字节接着是b? feQ **wI
w!fE;H8w6
|PC*=ykT3
j4qJ.i
如果您知道答案请在讨论中写出,以下是部份网友的答案,供参考: %Dwk
0#nPbe,Lj
网友rwxybh(行云)的答案: YW7b)uYf
内存布局是 >0"+4<72
1*** 11** C=eF.FB;'
1111 **** xg3:} LQ
1111 1111 8ji_#og
y3fGWa*7e
所以答案就是24和3 U&?v:&c#&n
Ytl4kaYS
下面是一个测试的程序,试一试就知道了,我用的是VC2005 EOCN&_Z;
6oGYnu;UZ
#pragma pack(8) BocSwf;v.
)ubiB^g'm
struct s1{ V,%=AR5
short a; // 2 BYtes S:OO0<W
long b; // 4 Bytes xL\0B,]
}; r,h%[JKM
struct s2{ >r !|sC
char c; // 1 Byte $m/)FnU/
s1 d; // 8 Bytes Ymg|4%O@
long long e; // 8 Bytes )c)vTZy
}; s,]z[qB#$
// 1*** 11** }hhGu\
// 1111 **** Y\No4w ^|d
// 1111 1111 , GP?amh
// k7T`bYv
neLAEHV
// 00 01 02 03 04 05 06 07 "thdPZ
// 00 01 02 03 04 05 06 07 Eea*s'
// 00 01 02 03 04 05 06 07 Dy:|g1>
// ]@phF _
#pragma pack()
sG
F aL
_no*k?o*
int main(int argc, char* argv[]) ?vbvBu{a
{ Z'.AA OG
s2 a; 0@%v1Oja
char *p = (char *)&a; *2,VyY
for(int i=0;i<24;++i) T( U_
p = (char)(i%8); `~By)?cT_>
printf("%d\n",sizeof(a)); 5fd]v<
printf("c=0x%lx\n",a.c); ~5}*
d
printf("d.a=0x%x\n",a.d.a); De'_SD|=
printf("d.b=0x%x\n",a.d.b); Zg{KFM%
printf("e=0x%llx\n",a.e); ppVHLrUh
return 0; @X#F3;
} }f6HYU
结果: oY H^_V
24 R8a3
1&
c=0x0 .nx2";oi
d.a=0x504 ` 2V19s]
d.b=0x3020100 %5"9</a&G
e=0x706050403020100 G$F<$
Wa{` VS
[q8 P~l
网友 redleaves (ID最吊的网友)的答案和分析: ) QU
!
t?iXZ
如果代码: @emK1iwm
#pragma pack(8) Ezd_`_@R
struct S1{ D$I5z.a
char a; wNpTM8rfU#
long b; j}.\]$J
};
CDK5
struct S2 { !xo{-@@wS
char c;
/} b03
struct S1 d; rrik,qyv6
long long e; Nh_Mz;ITuu
}; B#Vz#y
#pragma pack() r{L>
F]Tw
sizeof(S2)结果为24. 4R1<nZ"e~
成员对齐有一个重要的条件,即每个成员分别对齐.即每个成员按自己的方式对齐. vunHNHltW0
也就是说上面虽然指定了按8字节对齐,但并不是所有的成员都是以8字节对齐.其对齐的规则是,每个成员按其类型的对齐参数(通常是这个类型的大小)和指定对齐参数(这里是8字节)中较小的一个对齐.并且结构的长度必须为所用过的所有对齐参数的整数倍,不够就补空字节. jtW!"TOY
S.-TOE
S1中,成员a是1字节默认按1字节对齐,指定对齐参数为8,这两个值中取1,a按1字节对齐;成员b是4个字节,默认是按4字节对齐,这时就按4字节对齐,所以sizeof(S1)应该为8; Y[}>CYO
S2中,c和S1中的a一样,按1字节对齐,而d 是个结构,它是8个字节,它按什么对齐呢?对于结构来说,它的默认对齐方式就是它的所有成员使用的对齐参数中最大的一个,S1的就是4.所以,成员d就是按4字节对齐.成员e是8个字节,它是默认按8字节对齐,和指定的一样,所以它对到8字节的边界上,这时,已经使用了12个字节了,所以又添加了4个字节的空,从第16个字节开始放置成员e.这时,长度为24,已经可以被8(成员e按8字节对齐)整除.这样,一共使用了24个字节. #W4dkCd(pF
a b H4&lb}
S1的内存布局:11**,1111, L.*M&Ry
c S1.a S1.b d /<|%yE&KhJ
S2的内存布局:1***,11**,1111,****11111111 P2#XKG
K8GP@yD]M
这里有三点很重要: nxnv,AZG
1.每个成员分别按自己的方式对齐,并能最小化长度 <7/R,\Wg~
2.复杂类型(如结构)的默认对齐方式是它最长的成员的对齐方式,这样在成员是复杂类型时,可以最小化长度 7QiIiWqIWC
3.对齐后的长度必须是成员中最大的对齐参数的整数倍,这样在处理数组时可以保证每一项都边界对齐 \/zq7j
/
F4z g3
e> e}vZlX
网友xue23(xue23) 的答案和分析: @#T|Y&
@tNz Q8
有程序查一下各个变量的内存地址得知: R;uvkg[o
各个变量在内存中的位置为 FKDk +ojw
c***aa** _E@2ZnD2
bbbb**** lrlgz[
dddddddd W$hx,VEy`
测试代码为: &=] ~0$
s2 ss; 96( v
cout << "ss.c = " << &ss << endl ; `yrB->|vG
cout << "ss.d.a = " <<&ss.d.a << endl; cQy2"vtU
cout << "ss.d.b = " <<&(ss.d.b) < cout << "ss.d = " <<&ss.e << endl; zPn+V7F
print out 各个变量的内存地址不就可以看出来了吗。 "O3tq=Q
vWzm@
所以答案是24,2. =.Pw`.
S"NqM[W
但是我的想像中应该是这样的分布情况: /R]U}o^/(%
c******* tdBm
(CsN
aa**bbbb N
+Yxz;Mg
dddddddd GfoLae
[8 ]z|bM
不知为什么会c和a放在一起,组成8位长度。