Intel和微软同时出现的C语言面试题 eP-|3$
#pragma pack(8) `}Zqmfs
z{rV|vQ
struct s1{ -#|;qFD]
short a; l)%PvLbL
long b; DhyR
}; Z3S+")^
>O-KJZ'GV
struct s2{ +8Lbz^#
char c; GTdoUSUq
s1 d; %bi ie
long long e; [:y:_ECs6
}; T8o](:B~
m)Plv+R}
#pragma pack() fqgp{(`@>
6gV*G
问 #r'MfTr
1.sizeof(s2) = ? &b} \).5E
2.s2的s1中的a后面空了几个字节接着是b? uHg q"e
LiG$M{ 0
&i5@4,p y9
M =^d
如果您知道答案请在讨论中写出,以下是部份网友的答案,供参考: a^%iAe
pm6#azQ
网友rwxybh(行云)的答案: p) 8S]p]
内存布局是 s;VW
%e
1*** 11** r2=@1=?8
1111 **** )5}<@Ql
1111 1111 V`I4"}M1
7}kJp%-
所以答案就是24和3 ! ?g+'OM
ix!xLm9\
下面是一个测试的程序,试一试就知道了,我用的是VC2005 2ioHhcYdJU
A=N$5ZJ
#pragma pack(8) +RooU?Aq
7:jLZ!mgi
struct s1{ 7f>=-sv
short a; // 2 BYtes B>53+GyMV
long b; // 4 Bytes ok:uTeJI
}; S1QMS
struct s2{ uM2@&)u
char c; // 1 Byte g:Hj1!'
s1 d; // 8 Bytes ~:DL{ZeEb
long long e; // 8 Bytes xKUL}>8
}; 2%%\jlT_
// 1*** 11** =]7o+L4
// 1111 **** p!UR;xHI\
// 1111 1111 ALMsF2H
// o2!738
T9nb ~P[
// 00 01 02 03 04 05 06 07 e5'I W__
// 00 01 02 03 04 05 06 07 h4;kjr}h}
// 00 01 02 03 04 05 06 07 jK w
96
// G2`z?);1b
#pragma pack() ~5KcbGD~
`c
int main(int argc, char* argv[]) y!FO
{ | b'Ut)E
s2 a; E%mEfj7
char *p = (char *)&a; nfEbu4|
for(int i=0;i<24;++i) $[|(&8+7
p = (char)(i%8); ]m+%y+
printf("%d\n",sizeof(a)); n5}]C{s'
printf("c=0x%lx\n",a.c); QOWGQl%!
printf("d.a=0x%x\n",a.d.a); Bj@>iw?g'
printf("d.b=0x%x\n",a.d.b); ;R?@
D]
printf("e=0x%llx\n",a.e); ER"69zQg|2
return 0; ofy"SM
} \L Q+
n+
结果: _C !i(z!d
24 @DysM~I
c=0x0 AQ,lLn+
d.a=0x504 :iE b^F}
d.b=0x3020100 !Z$d<~Mq q
e=0x706050403020100 JEto_&8,C
`zQuhD 8W
Y1PR?c
Q
网友 redleaves (ID最吊的网友)的答案和分析: bzi"7%c
"Rj
PTRe:
如果代码: s=8H<'l
#pragma pack(8) & zDuh[j}
struct S1{ f.6>6%l
char a; dNe!X0[
long b; ]C \+b<
}; )?rq8VO
struct S2 { B>2R-pa4~
char c; Q"&Mr+
struct S1 d; V*?cMJ_G
long long e; F^%w%E\
}; .QvD603%5
#pragma pack() a'VQegP(f\
sizeof(S2)结果为24. C~En0 G1
成员对齐有一个重要的条件,即每个成员分别对齐.即每个成员按自己的方式对齐. 3aqH!?rVU
也就是说上面虽然指定了按8字节对齐,但并不是所有的成员都是以8字节对齐.其对齐的规则是,每个成员按其类型的对齐参数(通常是这个类型的大小)和指定对齐参数(这里是8字节)中较小的一个对齐.并且结构的长度必须为所用过的所有对齐参数的整数倍,不够就补空字节. aXe&c^AR
!l[;,l
S1中,成员a是1字节默认按1字节对齐,指定对齐参数为8,这两个值中取1,a按1字节对齐;成员b是4个字节,默认是按4字节对齐,这时就按4字节对齐,所以sizeof(S1)应该为8; F[ E'R.:
S2中,c和S1中的a一样,按1字节对齐,而d 是个结构,它是8个字节,它按什么对齐呢?对于结构来说,它的默认对齐方式就是它的所有成员使用的对齐参数中最大的一个,S1的就是4.所以,成员d就是按4字节对齐.成员e是8个字节,它是默认按8字节对齐,和指定的一样,所以它对到8字节的边界上,这时,已经使用了12个字节了,所以又添加了4个字节的空,从第16个字节开始放置成员e.这时,长度为24,已经可以被8(成员e按8字节对齐)整除.这样,一共使用了24个字节. '@{:FrG*U
a b io#}z4"'qY
S1的内存布局:11**,1111, KIF9[/P
c S1.a S1.b d 7b"fpB
S2的内存布局:1***,11**,1111,****11111111 i2<z"v63
GHv6UIe&
这里有三点很重要: 5 ^{~xOM5
1.每个成员分别按自己的方式对齐,并能最小化长度 *Soi
2.复杂类型(如结构)的默认对齐方式是它最长的成员的对齐方式,这样在成员是复杂类型时,可以最小化长度 khy'Y&\F;
3.对齐后的长度必须是成员中最大的对齐参数的整数倍,这样在处理数组时可以保证每一项都边界对齐 NW\CEJV
5H3o?x
w'@gzK
网友xue23(xue23) 的答案和分析: Nv5^2^Sc=
~~>m
有程序查一下各个变量的内存地址得知: !5*VBE\
各个变量在内存中的位置为 p4VARAqi
c***aa** ]Uv,}W
bbbb**** L)'G_)Sl
dddddddd f{9+,z
测试代码为: #T)Gkc"{
s2 ss; {hS!IOM
cout << "ss.c = " << &ss << endl ; I}8e"#
cout << "ss.d.a = " <<&ss.d.a << endl; ^>|ZN2
cout << "ss.d.b = " <<&(ss.d.b) < cout << "ss.d = " <<&ss.e << endl; bDl:,7;
print out 各个变量的内存地址不就可以看出来了吗。 /M2in]oH
K=f4<tP_
所以答案是24,2. h#0n2o #
;$D,w
但是我的想像中应该是这样的分布情况: T<]{:\*n
c******* WDc[+Xyw
aa**bbbb wv\X
dddddddd E1QJ^]MG.
4=,J@N-
不知为什么会c和a放在一起,组成8位长度。