Intel和微软同时出现的C语言面试题 ZY83,:<
#pragma pack(8) yPL@uCzA@
6,!]x>B
struct s1{ >Zr`9$i
short a; ?g!)[p`v
long b; q|S }5
}; =4?m>v,re
J<'4(}^|
struct s2{ RsE+\)
char c; y'(;!5w
s1 d; +Ta7b)
long long e; 6%)dsTAB
}; !4|7U\;
HH>]"mv
#pragma pack() /@0wbA
.6r&<*
问 U:_&aY_
1.sizeof(s2) = ? :Bl $c,J
2.s2的s1中的a后面空了几个字节接着是b? xC|7"N^/
*r%=p/oQ}B
|W?x6]~.R
I&4|T<j
如果您知道答案请在讨论中写出,以下是部份网友的答案,供参考: mp}ZHuf G
"BK&C6]
网友rwxybh(行云)的答案: t/HE@xPxI5
内存布局是 vrH/Z.WD
1*** 11** :Vv=p*~
1111 **** 7dAa~!/(
1111 1111 &QvWT+]c'0
^!=+$@<
所以答案就是24和3 4PNl3N3,n
xK
/NzVt
下面是一个测试的程序,试一试就知道了,我用的是VC2005 "S1+mSW>
18F7;d N8
#pragma pack(8) lrK5q
^"l4
struct s1{ I"r*p?
short a; // 2 BYtes syMB~g
long b; // 4 Bytes k5|h8%h8
}; PX+$Us
struct s2{ z1s9[5
char c; // 1 Byte x#U?~6.6
s1 d; // 8 Bytes WG9x_X&XJ
long long e; // 8 Bytes B+,Z 3*
}; 41$7P[M;
// 1*** 11** [9X1;bO#f
// 1111 **** mim]nRd2v
// 1111 1111
dY|(
// gwNv;g
hV_0f_Og
// 00 01 02 03 04 05 06 07 Y*J,9
// 00 01 02 03 04 05 06 07 ,myl9s
// 00 01 02 03 04 05 06 07 EFhe``
// p,U.5bX
#pragma pack() H~fZA)W 4Y
$kg!XT{V
int main(int argc, char* argv[]) O]`CSTv'_
{ j$BM$q/c
s2 a; F?3a22Zg#
char *p = (char *)&a; #TRPq>XzD
for(int i=0;i<24;++i) s<tdn[d
p = (char)(i%8); yo3'\I
printf("%d\n",sizeof(a)); FK0nQ{uB"
printf("c=0x%lx\n",a.c); /&a[D2
printf("d.a=0x%x\n",a.d.a); VcA87*pel
printf("d.b=0x%x\n",a.d.b); YaDr6)
printf("e=0x%llx\n",a.e); Sky!ZN'I
return 0; Xrc0RWXB8
} 7\<#z|
结果: c)+IX;q-C
24 0Kq\ oMn
c=0x0 T-uI CMEf
d.a=0x504 5_#wOz0u$
d.b=0x3020100 Y ~xcJH
e=0x706050403020100 ]=7}Y%6
l\JoWL
)FYz*:f>&
网友 redleaves (ID最吊的网友)的答案和分析: NbSkauF~b
X^7bOFWE
如果代码: zq8LQ4@ay
#pragma pack(8) U8;k6WT|
struct S1{ C([TolZ
char a; >^{}Hjt
long b; $s5LzJn
}; V_$ BZm%8J
struct S2 { RKx"
}<#+
char c; YOd0dKe
struct S1 d; Yc&yv
long long e; 9ssTG4Sa
}; ">j}!n
8J
#pragma pack() <%Bsb}h,
sizeof(S2)结果为24. 9Y3_.qa(.
成员对齐有一个重要的条件,即每个成员分别对齐.即每个成员按自己的方式对齐. c\065#f!
也就是说上面虽然指定了按8字节对齐,但并不是所有的成员都是以8字节对齐.其对齐的规则是,每个成员按其类型的对齐参数(通常是这个类型的大小)和指定对齐参数(这里是8字节)中较小的一个对齐.并且结构的长度必须为所用过的所有对齐参数的整数倍,不够就补空字节. >iDV8y
`a*[@a#
S1中,成员a是1字节默认按1字节对齐,指定对齐参数为8,这两个值中取1,a按1字节对齐;成员b是4个字节,默认是按4字节对齐,这时就按4字节对齐,所以sizeof(S1)应该为8; $b
QD{ {
S2中,c和S1中的a一样,按1字节对齐,而d 是个结构,它是8个字节,它按什么对齐呢?对于结构来说,它的默认对齐方式就是它的所有成员使用的对齐参数中最大的一个,S1的就是4.所以,成员d就是按4字节对齐.成员e是8个字节,它是默认按8字节对齐,和指定的一样,所以它对到8字节的边界上,这时,已经使用了12个字节了,所以又添加了4个字节的空,从第16个字节开始放置成员e.这时,长度为24,已经可以被8(成员e按8字节对齐)整除.这样,一共使用了24个字节. N[~RWg
a b )\8l6Gw
S1的内存布局:11**,1111, /z.Y<xOc
c S1.a S1.b d bODCC5yL
S2的内存布局:1***,11**,1111,****11111111 [8v v[n/
sFsp`kf
这里有三点很重要: =]K;"
1.每个成员分别按自己的方式对齐,并能最小化长度 @Xts}(L
2.复杂类型(如结构)的默认对齐方式是它最长的成员的对齐方式,这样在成员是复杂类型时,可以最小化长度 P{h;2b{
3.对齐后的长度必须是成员中最大的对齐参数的整数倍,这样在处理数组时可以保证每一项都边界对齐 Mpzt9*7R
}.>( [\q
kFg@|#0v9
网友xue23(xue23) 的答案和分析: gG!L#J?
c_"]AhV~Mg
有程序查一下各个变量的内存地址得知: `qbf_;\
各个变量在内存中的位置为 S-NKT(H)c
c***aa** s3Pr$h
bbbb**** ?Id3#+-O
dddddddd HZX(kYV
测试代码为: Kc$j<MRtv
s2 ss; kj{z;5-dl
cout << "ss.c = " << &ss << endl ; mmE\=i~
cout << "ss.d.a = " <<&ss.d.a << endl; omevF>b;
cout << "ss.d.b = " <<&(ss.d.b) < cout << "ss.d = " <<&ss.e << endl; MqDz cB]
print out 各个变量的内存地址不就可以看出来了吗。 '_N~PoV
.B_LQ;0:
所以答案是24,2. jdqVS @SD
JR] /\(
但是我的想像中应该是这样的分布情况: *](maF~%C
c******* '[Ap/:/UY
aa**bbbb .7 6T<j_
dddddddd .jA'BF.
gi\2bzWkbX
不知为什么会c和a放在一起,组成8位长度。