Intel和微软同时出现的C语言面试题 NUm3E4
#pragma pack(8) cZ o]*Gv.
}g(aZ
struct s1{ ?#]c{Tlpz
short a; >5]Xl*{H)
long b; vA+ RZ
}; `W|2Xi=^5
"7gS*v,r
struct s2{ ;'cv?3Y
char c; Lu-owP7nB
s1 d; @NX^__sa
long long e; MA"iM+Ar
}; ]>:%:-d6
s31^9a
#pragma pack() @dcW0WQ\
qf7.Sh
问 C'mmo&Pd
1.sizeof(s2) = ? s-k-|4
2.s2的s1中的a后面空了几个字节接着是b? eW\_9E)cY
ir/ 2/
E
~\XB'
- FE)
如果您知道答案请在讨论中写出,以下是部份网友的答案,供参考: x6F\|nb
!.p!
网友rwxybh(行云)的答案: @Z.Ne:*J
内存布局是 iiRK3m
1*** 11** Fbk<qQH
1111 **** y(N-1
1111 1111 BPi>SI0
R2M,VK?Wx
所以答案就是24和3 8f29Hj+
E1VCm[j2
下面是一个测试的程序,试一试就知道了,我用的是VC2005 ?F`lI""E
Jbs:}]2
#pragma pack(8) =XoNk1
Kji}2j'a
struct s1{ zJ &qR
short a; // 2 BYtes j*+r`CX
long b; // 4 Bytes *~fN^{B'!
}; M2V.FYV{j>
struct s2{ 3ON]c13
char c; // 1 Byte v[lytX4)
s1 d; // 8 Bytes BNzL+"W
long long e; // 8 Bytes 4"7Qz z
}; GW}KmTa]&
// 1*** 11** R %}k52`
// 1111 **** 9Z#37)
// 1111 1111 RRq*CLj
// EB\z:n5
G+5G,|}
// 00 01 02 03 04 05 06 07 P.[>x
// 00 01 02 03 04 05 06 07 {uckYx-A
// 00 01 02 03 04 05 06 07
# &M
// nP0}vX)<
#pragma pack() w7%N=hL1
s/A]&!`
int main(int argc, char* argv[]) Q/0}AQO
{ J-X5n 3I&
s2 a; Vy(lyD<6
char *p = (char *)&a; t`DUY3>36
for(int i=0;i<24;++i) sCnZ\C@u
p = (char)(i%8); EBebyQcon
printf("%d\n",sizeof(a)); ([$F5
q1TR
printf("c=0x%lx\n",a.c); _I'O4s1S
printf("d.a=0x%x\n",a.d.a); ClfpA?vv
printf("d.b=0x%x\n",a.d.b); cHR }`U$
printf("e=0x%llx\n",a.e); -Fl3m
return 0; 4+ 4?0R
} X>Xpx<RY!
结果: kfmIhHlYQ
24 ^5GS!u"
c=0x0 ,lN!XP{M6w
d.a=0x504 O|gb{
d.b=0x3020100 DR =>la}!
e=0x706050403020100 89 SsS b
r
Ssv^W+
k$+&
网友 redleaves (ID最吊的网友)的答案和分析: huN(Q{fj
S>H W`
如果代码: {= z%('^
#pragma pack(8) s)To#
struct S1{ 1pz6e8p:m
char a; otPEJ^W&
long b; `|PxEif+J
}; FyY;F;4P
struct S2 { |d:URuG~:I
char c; +rql7D0st
struct S1 d; B:^U~s R
long long e; bH,Jddc
}; Je?V']lm
#pragma pack() NgH%
sizeof(S2)结果为24. ob*2V!"
成员对齐有一个重要的条件,即每个成员分别对齐.即每个成员按自己的方式对齐. ]=_BK!O
也就是说上面虽然指定了按8字节对齐,但并不是所有的成员都是以8字节对齐.其对齐的规则是,每个成员按其类型的对齐参数(通常是这个类型的大小)和指定对齐参数(这里是8字节)中较小的一个对齐.并且结构的长度必须为所用过的所有对齐参数的整数倍,不够就补空字节. ,fYO>l';`f
f0hi70\(X
S1中,成员a是1字节默认按1字节对齐,指定对齐参数为8,这两个值中取1,a按1字节对齐;成员b是4个字节,默认是按4字节对齐,这时就按4字节对齐,所以sizeof(S1)应该为8; m7 !l3W2
S2中,c和S1中的a一样,按1字节对齐,而d 是个结构,它是8个字节,它按什么对齐呢?对于结构来说,它的默认对齐方式就是它的所有成员使用的对齐参数中最大的一个,S1的就是4.所以,成员d就是按4字节对齐.成员e是8个字节,它是默认按8字节对齐,和指定的一样,所以它对到8字节的边界上,这时,已经使用了12个字节了,所以又添加了4个字节的空,从第16个字节开始放置成员e.这时,长度为24,已经可以被8(成员e按8字节对齐)整除.这样,一共使用了24个字节. J4co@=AJ
a b B3yn:=80
S1的内存布局:11**,1111, "=
%-
c S1.a S1.b d %Z}dY~:
S2的内存布局:1***,11**,1111,****11111111 WcUeWGC>
E+3~w?1
这里有三点很重要: Pb~S{):
1.每个成员分别按自己的方式对齐,并能最小化长度 5hDE&hp
2.复杂类型(如结构)的默认对齐方式是它最长的成员的对齐方式,这样在成员是复杂类型时,可以最小化长度 *Pq`~W_M7
3.对齐后的长度必须是成员中最大的对齐参数的整数倍,这样在处理数组时可以保证每一项都边界对齐 >#8`Zy:/Y
1 9)78kV{
rP3)TeG6
网友xue23(xue23) 的答案和分析:
,p 'M@[
S"_vD<q
有程序查一下各个变量的内存地址得知: r+Z+x{
各个变量在内存中的位置为 ;eA~z"g
c***aa** S)[2\Z{**T
bbbb**** Xt~/8)&
dddddddd S[ 2`7'XV
测试代码为: Ads^y`b
s2 ss; Bq2}nDP
cout << "ss.c = " << &ss << endl ; LLU>c]a
cout << "ss.d.a = " <<&ss.d.a << endl; d3 N %V.w
cout << "ss.d.b = " <<&(ss.d.b) < cout << "ss.d = " <<&ss.e << endl; 5aWKyXBIx
print out 各个变量的内存地址不就可以看出来了吗。 z&-`<uV~
h?CNChRJs
所以答案是24,2. t8^*s<O
0\gE^=o[
但是我的想像中应该是这样的分布情况: w$t2Hd
c******* f,?7,? x
aa**bbbb DSnsi@Mi
dddddddd ~MQN&
?Ts
Z_
不知为什么会c和a放在一起,组成8位长度。