Intel和微软同时出现的C语言面试题 ?Qb<-~~
j1
#pragma pack(8) <8UYhGK
_2b tfY1U
struct s1{ LQnkcV
short a; 10#oG{9
long b; VL'
fP2
}; \D>$aLO*?
MxzLK%am
struct s2{ T]Nu)
char c; ?^:h\C^a"
s1 d; b;|55Y
long long e; VL9-NfeqR
}; H A}f,),G
XPB9~::
#pragma pack() D@EO=08<b
gn5)SP 8
问 v){ .Z^_C
1.sizeof(s2) = ? /ug8]Lo0
2.s2的s1中的a后面空了几个字节接着是b? XWJwJ
xoB},Xl$D
e6=]m#O9
s95vK7I
如果您知道答案请在讨论中写出,以下是部份网友的答案,供参考: crO@?m1
BQ^H? jo
网友rwxybh(行云)的答案: s<x1>Q7X~
内存布局是 +7Kyyu)y@
1*** 11** &;LqF#ZL
1111 **** .^)UO
1111 1111 .I3?7
(BX83)
所以答案就是24和3 2/,0iwj-
uH3D{4
下面是一个测试的程序,试一试就知道了,我用的是VC2005 D+lzFn$3
lq.Te,Y%w
#pragma pack(8) @eqeN9e
hzI*{
struct s1{ )o!XWh
short a; // 2 BYtes (2?G:+C 7
long b; // 4 Bytes ozsxXBh-`'
}; z}SND9-"
struct s2{ PLM _#+R>
char c; // 1 Byte 1
4LI5T
s1 d; // 8 Bytes ~.PP30'
long long e; // 8 Bytes TEUY3z[g
}; # N~,F@t
// 1*** 11** BiE08,nj
// 1111 **** Bs`$ i ;&
// 1111 1111 K[
.JlIP
// 4^6.~6a
+b;hBb]R
// 00 01 02 03 04 05 06 07 F2(q>#<_
// 00 01 02 03 04 05 06 07 vUC!fIG
// 00 01 02 03 04 05 06 07 5CAR{|a
// ashcvn~z
#pragma pack() QD{:vG
g
`h;k2Se5
int main(int argc, char* argv[]) 9^P2I)aD
{ Kex[ >L10G
s2 a; 0ZAj=u@O
char *p = (char *)&a; g|P C$p-z+
for(int i=0;i<24;++i) 0f ER*.F
p = (char)(i%8); F{k+7Ftc
printf("%d\n",sizeof(a)); Dj-s5pAW
printf("c=0x%lx\n",a.c); gG54:
printf("d.a=0x%x\n",a.d.a); N132sN2
printf("d.b=0x%x\n",a.d.b); fYebB7Pv
printf("e=0x%llx\n",a.e); eT"Uxhs-}
return 0; "rXOsX\;
} bM;`s5d
结果: B68H&h]D#'
24 JU0]Wq <^[
c=0x0 T+"f]v
d.a=0x504 "$p#&W69"J
d.b=0x3020100 zH)_vW
e=0x706050403020100 ? y},,
]pTvMom$6
cu#e38M&eE
网友 redleaves (ID最吊的网友)的答案和分析: j'Y/ H5
h
-_&MD/J
如果代码: a7H0!9^h
#pragma pack(8) z xD,E@lF
struct S1{ (g/7yO(s
char a; l52a\/
long b; jStmS2n
}; kD~uGA
struct S2 { \hk/1/siyF
char c; [2$4| ;7
struct S1 d; g=]&A
long long e; g;F"7
^sg
}; ^<V9'Ut
#pragma pack() _|c&@M
sizeof(S2)结果为24.
#S
QXTR
成员对齐有一个重要的条件,即每个成员分别对齐.即每个成员按自己的方式对齐. 1uG=`k8'k
也就是说上面虽然指定了按8字节对齐,但并不是所有的成员都是以8字节对齐.其对齐的规则是,每个成员按其类型的对齐参数(通常是这个类型的大小)和指定对齐参数(这里是8字节)中较小的一个对齐.并且结构的长度必须为所用过的所有对齐参数的整数倍,不够就补空字节. O]u",J5
90 {tI X
S1中,成员a是1字节默认按1字节对齐,指定对齐参数为8,这两个值中取1,a按1字节对齐;成员b是4个字节,默认是按4字节对齐,这时就按4字节对齐,所以sizeof(S1)应该为8; -@%%*YI>
S2中,c和S1中的a一样,按1字节对齐,而d 是个结构,它是8个字节,它按什么对齐呢?对于结构来说,它的默认对齐方式就是它的所有成员使用的对齐参数中最大的一个,S1的就是4.所以,成员d就是按4字节对齐.成员e是8个字节,它是默认按8字节对齐,和指定的一样,所以它对到8字节的边界上,这时,已经使用了12个字节了,所以又添加了4个字节的空,从第16个字节开始放置成员e.这时,长度为24,已经可以被8(成员e按8字节对齐)整除.这样,一共使用了24个字节. jy$@a%FD
a b vM0_>1nN
S1的内存布局:11**,1111, C;1PsSE+A
c S1.a S1.b d tR`S#rk
S2的内存布局:1***,11**,1111,****11111111 8q_0,>w%
m$UvFP1>u1
这里有三点很重要: \4~AI=aw,T
1.每个成员分别按自己的方式对齐,并能最小化长度 Hw_o
w?
2.复杂类型(如结构)的默认对齐方式是它最长的成员的对齐方式,这样在成员是复杂类型时,可以最小化长度 go|>o5!g
3.对齐后的长度必须是成员中最大的对齐参数的整数倍,这样在处理数组时可以保证每一项都边界对齐 a#(U2OP
<,39_#H?F3
`bgb*Yaod
网友xue23(xue23) 的答案和分析: .Oo/y0E^
n`5WXpz4;
有程序查一下各个变量的内存地址得知: w$Ux?y-L
各个变量在内存中的位置为 Y5TS>iEE]
c***aa** wz#[:2
bbbb**** s"mFt{Y
dddddddd W}gVIfe
测试代码为: lJ/6-dP
s2 ss; ~Yk"Hos
cout << "ss.c = " << &ss << endl ; qb7^VIo%c
cout << "ss.d.a = " <<&ss.d.a << endl; }5S2p@W)
cout << "ss.d.b = " <<&(ss.d.b) < cout << "ss.d = " <<&ss.e << endl; `"<2)yq?
print out 各个变量的内存地址不就可以看出来了吗。 =:K@zlO:
v4<j
所以答案是24,2. OhWC}s
X\A]"su
但是我的想像中应该是这样的分布情况: 3z,2utH
c******* #tz8{o?ebN
aa**bbbb _
VKgs]Y
dddddddd Z;*`fd?8
70`M,``
不知为什么会c和a放在一起,组成8位长度。