Intel和微软同时出现的C语言面试题 7mYBxE/
#pragma pack(8) 2'WdH1UrBc
X'5+)dj
struct s1{ gWy2E;"a
short a; BgwZZ<B
long b; ?D]T|=EZY
}; S4%MnT6Uy
@_?8I_\:
struct s2{ DO?
bJ01
char c; [~ |e:
s1 d; Y0nuwX*{
long long e; W97
&[([
}; N-GQ\&
}q~xr3#
#pragma pack() wqp(E+&
;%PdSG=U
问 @_Ly^'
"
1.sizeof(s2) = ? z(beT e
2.s2的s1中的a后面空了几个字节接着是b? Vt
U
DYCXzFAa
XcQ'(
!& xc.39
如果您知道答案请在讨论中写出,以下是部份网友的答案,供参考: hH@pA:`s
w5}2$r
网友rwxybh(行云)的答案: ;AgXl%Q
内存布局是 ?ik6kWI
1*** 11** yO09NQ 5u
1111 **** `!g
XA.9Uv
1111 1111 %GDs/9
x^]1m%
所以答案就是24和3 $kk!NAW
t2vo;,^euL
下面是一个测试的程序,试一试就知道了,我用的是VC2005 #oD*H:%*
5VPP 2;J
#pragma pack(8) Nh|QYxOP
{piZm12q?
struct s1{ T1r^.;I:
short a; // 2 BYtes oGi{d5
long b; // 4 Bytes kT6EHuB
}; IK^jzx
struct s2{ ~WG#Zci-
char c; // 1 Byte 2*1s(Jro
s1 d; // 8 Bytes 6~v|pA jY
long long e; // 8 Bytes goV[C]|
}; G|Y9F|.!
// 1*** 11** nANoy6z:
// 1111 **** {CR'Z0
// 1111 1111 FucLcq2Z
// L3-tD67oa
+Ss|4O}'
// 00 01 02 03 04 05 06 07 ?(CMm%(8
// 00 01 02 03 04 05 06 07 f
i3 <
// 00 01 02 03 04 05 06 07 S?_ ;$Cn
// 0BTLIV$d;
#pragma pack() \WVrn >%xu
L?n*b
int main(int argc, char* argv[]) U8(Rye$
{ L_YVe(dT
s2 a; It@ak6u?
char *p = (char *)&a; 5? s$(Lt~
for(int i=0;i<24;++i) (U |[C*
p = (char)(i%8); 8?r
,ylUj
printf("%d\n",sizeof(a)); $Y4;Xe=
printf("c=0x%lx\n",a.c); /IC7q?avQN
printf("d.a=0x%x\n",a.d.a); }X3SjNd q
printf("d.b=0x%x\n",a.d.b); @M-+-6+
printf("e=0x%llx\n",a.e); ^.J
F?2T/
return 0; QMfa~TH#p
} D`lTP(] y
结果: wKCHG/W
24 ccJ@jpXI
c=0x0 RYaf{i`
d.a=0x504 D/Y .'P:j
d.b=0x3020100 2c
<Qh=
e=0x706050403020100 451r!U1Z
N}>XBZy
{7)D/WY5
网友 redleaves (ID最吊的网友)的答案和分析: KFd"JtPg
2hRaYX,g
如果代码: ]iuM2]
#pragma pack(8) 3I?? K)Yl
struct S1{ H85HL-{
char a; $@t-Oor;
long b; S"UFT-N
}; 0EYK3<k9!
struct S2 { p
IXBJk
char c; 4XDR?KUM
struct S1 d; a'ViyTBo
long long e; tH<v1LEZN
}; QtQku1{
#pragma pack() l'(Cxhf.W
sizeof(S2)结果为24. *tjE#TW
成员对齐有一个重要的条件,即每个成员分别对齐.即每个成员按自己的方式对齐. Z^>[{|lIA
也就是说上面虽然指定了按8字节对齐,但并不是所有的成员都是以8字节对齐.其对齐的规则是,每个成员按其类型的对齐参数(通常是这个类型的大小)和指定对齐参数(这里是8字节)中较小的一个对齐.并且结构的长度必须为所用过的所有对齐参数的整数倍,不够就补空字节. SU9#Y|I
d^IOB|6Q
S1中,成员a是1字节默认按1字节对齐,指定对齐参数为8,这两个值中取1,a按1字节对齐;成员b是4个字节,默认是按4字节对齐,这时就按4字节对齐,所以sizeof(S1)应该为8; <w}k9(Ds
S2中,c和S1中的a一样,按1字节对齐,而d 是个结构,它是8个字节,它按什么对齐呢?对于结构来说,它的默认对齐方式就是它的所有成员使用的对齐参数中最大的一个,S1的就是4.所以,成员d就是按4字节对齐.成员e是8个字节,它是默认按8字节对齐,和指定的一样,所以它对到8字节的边界上,这时,已经使用了12个字节了,所以又添加了4个字节的空,从第16个字节开始放置成员e.这时,长度为24,已经可以被8(成员e按8字节对齐)整除.这样,一共使用了24个字节. SM5i3EcFYP
a b "';'*x
S1的内存布局:11**,1111, O k_I}X
c S1.a S1.b d :*e0Z2=
S2的内存布局:1***,11**,1111,****11111111 h%(dT/jPL)
E) >~0jv
这里有三点很重要: _tL*sA>[~)
1.每个成员分别按自己的方式对齐,并能最小化长度 0%}$@H5i
2.复杂类型(如结构)的默认对齐方式是它最长的成员的对齐方式,这样在成员是复杂类型时,可以最小化长度 [syuoJ
3.对齐后的长度必须是成员中最大的对齐参数的整数倍,这样在处理数组时可以保证每一项都边界对齐 fEdQR->
J1Mm,LTO
(^Xp\dyZL
网友xue23(xue23) 的答案和分析: tn;e
PcU
Nm#VA.~
有程序查一下各个变量的内存地址得知: \w^iSK-
各个变量在内存中的位置为 &TSt/b/+W
c***aa** J}TS-j0
bbbb**** :N%cIxrqP
dddddddd ;'dw`)~jQ
测试代码为: oDx*}[/
s2 ss; ?};}#%971
cout << "ss.c = " << &ss << endl ; 3`J?as@^8
cout << "ss.d.a = " <<&ss.d.a << endl; A7
.[OC
cout << "ss.d.b = " <<&(ss.d.b) < cout << "ss.d = " <<&ss.e << endl; |v}"UW(y
print out 各个变量的内存地址不就可以看出来了吗。 #18H
Z4N
(zBa2Vmmv
所以答案是24,2. ;or(:Yoc-
42:\1B#[
但是我的想像中应该是这样的分布情况: 09 eS&J<R
c******* Uq~{=hMX
aa**bbbb Q<d\K(<3?:
dddddddd s7SW4ff1
E$34myOVf
不知为什么会c和a放在一起,组成8位长度。