Intel和微软同时出现的C语言面试题 Q>Z~={"
#pragma pack(8) M."/"hV`-
([>__c/Nd
struct s1{
J9*;Bqzim
short a; 7_l
Wr
long b; )lS04|s
}; `NgQ>KV!
_LC*_LT_
struct s2{ v G\J8s
char c; 37a1O>A
s1 d; z+6PVQ
long long e; IjRUr \ l
}; WH1" HO
C5I7\9F)
#pragma pack() l9a81NF{s
sRT H_]c
问 `VO;\s$5j
1.sizeof(s2) = ? !8[A;+o3P
2.s2的s1中的a后面空了几个字节接着是b? q@[F|EF=
*9kg\#
Z Se30Rl\
X 5
or5v
如果您知道答案请在讨论中写出,以下是部份网友的答案,供参考: ~i?A!
#\Rxqh7
网友rwxybh(行云)的答案: z|%Pi J,
内存布局是 X5[t6q!
1*** 11** Er~KX3vF
1111 **** .9B@w+=6
1111 1111 .Hqq!&
FP=-
jf/
所以答案就是24和3 d!R+-Fp
[(#)9/3,
下面是一个测试的程序,试一试就知道了,我用的是VC2005 7:uz{xPK6
X coPkW
#pragma pack(8) Q> y!
_1G/qHf^S
struct s1{ &k}B66
short a; // 2 BYtes DAWF
=p]
long b; // 4 Bytes q 9xA.*
}; Pm)*zdZ8
struct s2{ $G"\@YC<
char c; // 1 Byte "ckK{kS4~
s1 d; // 8 Bytes W#P\hx
long long e; // 8 Bytes [ R+M .5
}; {zm8`
// 1*** 11** @U5gxK*
// 1111 **** 9]IZ3
fQX
// 1111 1111 <af#
C2`B
// ,v8e7T
16 `M=R
// 00 01 02 03 04 05 06 07 Icg-rwa<Z
// 00 01 02 03 04 05 06 07 v8y Cf7+"
// 00 01 02 03 04 05 06 07 {*GBUv5
// g&2g>]
#pragma pack() Y3:HQ0w`|
W)Y`8&,
int main(int argc, char* argv[]) 6&SNFOX{@
{ zytN leyc
s2 a; \z !lw
char *p = (char *)&a; m6BUKX\m
for(int i=0;i<24;++i) Ii[U%
p = (char)(i%8); ;u'VR}4ph
printf("%d\n",sizeof(a)); ^\O*e)#*
printf("c=0x%lx\n",a.c); Y"8@\73(R
printf("d.a=0x%x\n",a.d.a); MjC<N[WO>N
printf("d.b=0x%x\n",a.d.b); TCyev[(
printf("e=0x%llx\n",a.e); o<!H/PN
return 0; $aJay]F
} t>}S@T{~T
结果: T=42]h
24 SQf[1}$ .
c=0x0 !vu-`u~86
d.a=0x504 Kj
@<$ChZw
d.b=0x3020100 Oz-/0;1n
e=0x706050403020100 V9"R8*@-
ig.Z,R3@r
_%2ukuJ `
网友 redleaves (ID最吊的网友)的答案和分析: &57~i=A
3
|wuTw|
如果代码: 7:vl -ZW
#pragma pack(8) X(BxC<!D.
struct S1{ nN<,rN{:
char a;
p )JR5z
long b; |Sjy
}; SQK82/
struct S2 { 8ly)G
char c; !|4]V}JQ
struct S1 d; &&C70+_po
long long e; G^dp9A
}; Ij4q &i"
#pragma pack() hizM}d-"C
sizeof(S2)结果为24. ?y>ji1
成员对齐有一个重要的条件,即每个成员分别对齐.即每个成员按自己的方式对齐. '1b8>L
也就是说上面虽然指定了按8字节对齐,但并不是所有的成员都是以8字节对齐.其对齐的规则是,每个成员按其类型的对齐参数(通常是这个类型的大小)和指定对齐参数(这里是8字节)中较小的一个对齐.并且结构的长度必须为所用过的所有对齐参数的整数倍,不够就补空字节. Bcv{Y\x;ko
RA<ky*^dr
S1中,成员a是1字节默认按1字节对齐,指定对齐参数为8,这两个值中取1,a按1字节对齐;成员b是4个字节,默认是按4字节对齐,这时就按4字节对齐,所以sizeof(S1)应该为8; WIi,`/K+
S2中,c和S1中的a一样,按1字节对齐,而d 是个结构,它是8个字节,它按什么对齐呢?对于结构来说,它的默认对齐方式就是它的所有成员使用的对齐参数中最大的一个,S1的就是4.所以,成员d就是按4字节对齐.成员e是8个字节,它是默认按8字节对齐,和指定的一样,所以它对到8字节的边界上,这时,已经使用了12个字节了,所以又添加了4个字节的空,从第16个字节开始放置成员e.这时,长度为24,已经可以被8(成员e按8字节对齐)整除.这样,一共使用了24个字节. VZcW
3/Y
a b >fP;H}S6
S1的内存布局:11**,1111, l]zQSXip
c S1.a S1.b d L1!~T+%uQ
S2的内存布局:1***,11**,1111,****11111111 Ir>4- @
s;oe Qa}TB
这里有三点很重要: hv#$Zo<
1.每个成员分别按自己的方式对齐,并能最小化长度 nrev!h
2.复杂类型(如结构)的默认对齐方式是它最长的成员的对齐方式,这样在成员是复杂类型时,可以最小化长度 ^ fC2o%3^
3.对齐后的长度必须是成员中最大的对齐参数的整数倍,这样在处理数组时可以保证每一项都边界对齐 zKJQel5
\w1XOm [)
`x
_(EZ
网友xue23(xue23) 的答案和分析: eJ45:]_%I@
N(4y}-w$
有程序查一下各个变量的内存地址得知: }gXhN"
各个变量在内存中的位置为 L{jx'[C
c***aa** wMCg`rk
bbbb**** &\6},JN
dddddddd aeN #<M&$<
测试代码为: =ZURh_{xV
s2 ss; ]}b
cout << "ss.c = " << &ss << endl ; tTTHQ7o*BD
cout << "ss.d.a = " <<&ss.d.a << endl; "0PsCr}!
cout << "ss.d.b = " <<&(ss.d.b) < cout << "ss.d = " <<&ss.e << endl; {u
y^Bui}
print out 各个变量的内存地址不就可以看出来了吗。 b?`2LAgn
7$%G3Q|)L
所以答案是24,2. ; ,sNRES3
.E^w, o
但是我的想像中应该是这样的分布情况: 80Hi v
c******* g!_#$az3
aa**bbbb %JSRC<,a
dddddddd O(%6/r`L,k
3\P*"65
不知为什么会c和a放在一起,组成8位长度。