Intel和微软同时出现的C语言面试题 Yk5Cyq
#pragma pack(8) 5Veybchy "
]ov"&,J
struct s1{ RaB%N$.9s
short a; _({K6adb
long b; PJ'@! jx
}; 0,m@BsK
AkBEE
struct s2{ m# I
char c; G88g@Exk
s1 d; -}Gk@=$G
long long e; ;5=5HYx%
}; `wLMJ,@f.
WOf*1C
#pragma pack() MT.D#jv&
t8S,C4
问 S d]`)
1.sizeof(s2) = ? }U$p[Gi<
2.s2的s1中的a后面空了几个字节接着是b? (s!cd]Qa.
)}T0SGY
19^B610
oz\r0:
如果您知道答案请在讨论中写出,以下是部份网友的答案,供参考: liVj-*m
Gu
K!<-Oz"
网友rwxybh(行云)的答案: ziD+% -
内存布局是 k0-,qM#p;X
1*** 11** <>[]-Vq
1111 **** (1;%V>,L
1111 1111 mV'^4by
I$1~;!<
所以答案就是24和3 #jX%nqMxW
{b26DKkQS
下面是一个测试的程序,试一试就知道了,我用的是VC2005 N`!=z++G
98t|G5
#pragma pack(8) "\x\P)j0>
2]-xmS>|b
struct s1{ `Z~\&r=
short a; // 2 BYtes Tg#%5~IX
long b; // 4 Bytes 2ee((vO&
}; x'`L(C
struct s2{ t+O7dZt%r
char c; // 1 Byte sqk$q pV6
s1 d; // 8 Bytes -hpMd/F
long long e; // 8 Bytes 1$rrfg
}; T\$r|
// 1*** 11** oA$]%
// 1111 **** I=wA)Bli1p
// 1111 1111 /mFa*~dj2
// g+92}$_
mi$*,fz
// 00 01 02 03 04 05 06 07 ~JxAo\2i
// 00 01 02 03 04 05 06 07 /?
HLEX
// 00 01 02 03 04 05 06 07 ryoD 1OE
// .g95E<bd
#pragma pack() L9(!L$
NW@guhK.
int main(int argc, char* argv[]) .eM
A*C~n
{ @P}!mdH1
s2 a; s4Y7x.-
char *p = (char *)&a; '5m`[S-IU
for(int i=0;i<24;++i) 'Lv>!s 7
p = (char)(i%8); "r.eN_d
printf("%d\n",sizeof(a)); :TN^}RML
printf("c=0x%lx\n",a.c); p+d?k"WN?
printf("d.a=0x%x\n",a.d.a); k6W
[//
printf("d.b=0x%x\n",a.d.b); pbb6?R,
printf("e=0x%llx\n",a.e); F5;x>;r
return 0; \H$j["3
} %4HpTx
结果: V/i7Z h#2:
24 vd!|k5t[d
c=0x0 $Xr9<)?,
d.a=0x504 ]{'lV~fc
d.b=0x3020100 E7UYJ)6]
e=0x706050403020100 4+_r0
}@S''AA\
~V<62"G
网友 redleaves (ID最吊的网友)的答案和分析: G9i?yd4n=B
Sej\Gt
如果代码: E;C=V2#>[
#pragma pack(8) /J0ctJ2k
struct S1{ +idp1SJ4
char a; 6 N.+
long b; l:rT{l=8*
}; a#:K"Mf.
struct S2 { ^zVBS7`J
char c; ISl-W1u}
struct S1 d; 7BDoF!kCx
long long e; $+.!(Js"K
}; L;s,x V
#pragma pack() t|y`Bl2
sizeof(S2)结果为24. $6p|}<u
成员对齐有一个重要的条件,即每个成员分别对齐.即每个成员按自己的方式对齐. B\}B
H
也就是说上面虽然指定了按8字节对齐,但并不是所有的成员都是以8字节对齐.其对齐的规则是,每个成员按其类型的对齐参数(通常是这个类型的大小)和指定对齐参数(这里是8字节)中较小的一个对齐.并且结构的长度必须为所用过的所有对齐参数的整数倍,不够就补空字节. KF4}cM=.5
m^Xq<`e"<
S1中,成员a是1字节默认按1字节对齐,指定对齐参数为8,这两个值中取1,a按1字节对齐;成员b是4个字节,默认是按4字节对齐,这时就按4字节对齐,所以sizeof(S1)应该为8; bp?4)C*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个字节. >rb8A6
a b -v7O*xm"
S1的内存布局:11**,1111, {]CO;5:
c S1.a S1.b d F/I`EV
S2的内存布局:1***,11**,1111,****11111111 q-)Ynp4'
c-{;P>L
这里有三点很重要: P_f^gB7
1.每个成员分别按自己的方式对齐,并能最小化长度 ?h4Rh0rkX
2.复杂类型(如结构)的默认对齐方式是它最长的成员的对齐方式,这样在成员是复杂类型时,可以最小化长度 49m}~J=*
3.对齐后的长度必须是成员中最大的对齐参数的整数倍,这样在处理数组时可以保证每一项都边界对齐 C0@[4a$8f
B&oP0 jS
d;9F2,k$w
网友xue23(xue23) 的答案和分析: G`"
9/FI7
96$qH{]Ap
有程序查一下各个变量的内存地址得知: #+,O
各个变量在内存中的位置为 RRH[$jk
c***aa** 9!06R-h
bbbb**** ai,Nx:r
dddddddd 5*W<6ia
测试代码为: XLNR%)l
s2 ss; k^Q>
cout << "ss.c = " << &ss << endl ; Lu@'Ee!>G
cout << "ss.d.a = " <<&ss.d.a << endl; N}tiaL4
cout << "ss.d.b = " <<&(ss.d.b) < cout << "ss.d = " <<&ss.e << endl; QirS=H+~
print out 各个变量的内存地址不就可以看出来了吗。 h (1 }g/
pZv>{=2hOS
所以答案是24,2. zU1[+JJY"{
aV'r
oxM
但是我的想像中应该是这样的分布情况: 2PSt*(
c******* [C"[#7
aa**bbbb H*]B7?S
dddddddd `K^j:fE7n
8P#jC$<
不知为什么会c和a放在一起,组成8位长度。