Intel和微软同时出现的C语言面试题 +Z~!n
#pragma pack(8) _JIUds5
4yZ+,hqJ<9
struct s1{ l%U_iqL&
short a; %R*vSRG/U
long b; jP.b oj_u*
}; 9`n)"r
S@zkoj@
struct s2{ c1A G3Nb
char c; 4FE@s0M,
s1 d; >AX~c
jo
long long e; 1
u_24
}; .C;_4jE
?r E]s!K
#pragma pack() {$1$]p~3o
B"Kce"!
问 IgR"euU
1.sizeof(s2) = ? {AL9o2
2.s2的s1中的a后面空了几个字节接着是b? CC(*zrOd-
S{(p<%)[
q(tGbhQ
h4.=sbzZ
如果您知道答案请在讨论中写出,以下是部份网友的答案,供参考: ;zE5(3x
#!u51P1
网友rwxybh(行云)的答案: $EGRaps{j>
内存布局是 chMc(.cN0
1*** 11** fDEu%fUYZ
1111 **** }Wche/g`
1111 1111 /<7C[^h{-
PWN'.HQ
所以答案就是24和3 /b:t;0G
i Kk"j
下面是一个测试的程序,试一试就知道了,我用的是VC2005 =Pb5b6Y@6
5-WRv;
#pragma pack(8) -0VA!3l
Li-(p"
struct s1{ oBNX8%5w
short a; // 2 BYtes T'b/]&0Tio
long b; // 4 Bytes 8u'O`j
}; =6:L +V
struct s2{ T<e7(=
char c; // 1 Byte @-&(TRbZo
s1 d; // 8 Bytes w Al}:|+n
long long e; // 8 Bytes eBC%2TF
}; ZecvjbnVY
// 1*** 11** #W%)$kc
// 1111 **** ^?7dOW
// 1111 1111 vG<pc_ak
// ?9gTk
\s?R
d1TdH s\
// 00 01 02 03 04 05 06 07 Jg|cvu-+
// 00 01 02 03 04 05 06 07 s\C8t0C
// 00 01 02 03 04 05 06 07 it\DZGsg
// #;"D)C
#pragma pack() :IR9=nhS]
iA3>X-x
int main(int argc, char* argv[]) d=Df.H+3
{ }uI7\\S
s2 a; #3Ej0"A@-B
char *p = (char *)&a; >'}=.3\
for(int i=0;i<24;++i) ey\m)6A$
p = (char)(i%8); $#!UGY
printf("%d\n",sizeof(a)); .Y(lB=pV
printf("c=0x%lx\n",a.c); Z2rzb{oS}
printf("d.a=0x%x\n",a.d.a); %t~SOkx
printf("d.b=0x%x\n",a.d.b); b WbXh$
printf("e=0x%llx\n",a.e); EwD3d0udL
return 0; `kNi*I^
} Vp]D
结果: "rx^M*"
24 ^K.u
~p
c=0x0 phgexAq
d.a=0x504 6vgBqn[
d.b=0x3020100 8@%mnyQ
e=0x706050403020100 N=T.l*8
0939i_
hH1lgc
网友 redleaves (ID最吊的网友)的答案和分析: x9)aBB
k]Alp;hVd
如果代码: %h" qMs S
#pragma pack(8) {+"g':><
struct S1{ Ki/'Ic1
char a; ,]Ro',A&
long b; (/SGT$#8
}; jWXR__>.
struct S2 { P1i*u0a
char c; ^}o7*
struct S1 d; *!g 24
long long e; ;Rhb@]X
}; ms}f>f=
#pragma pack() @GG(7r\/B
sizeof(S2)结果为24. /}w#Jk4pD
成员对齐有一个重要的条件,即每个成员分别对齐.即每个成员按自己的方式对齐. WgA`kT
也就是说上面虽然指定了按8字节对齐,但并不是所有的成员都是以8字节对齐.其对齐的规则是,每个成员按其类型的对齐参数(通常是这个类型的大小)和指定对齐参数(这里是8字节)中较小的一个对齐.并且结构的长度必须为所用过的所有对齐参数的整数倍,不够就补空字节. ^Ue0mC7m
H\fcY p6
S1中,成员a是1字节默认按1字节对齐,指定对齐参数为8,这两个值中取1,a按1字节对齐;成员b是4个字节,默认是按4字节对齐,这时就按4字节对齐,所以sizeof(S1)应该为8; JAlU%n?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个字节. (S
k#x
a b ]^:hyOK
S1的内存布局:11**,1111,
@8=vFP'
c S1.a S1.b d I( ]BMMj
S2的内存布局:1***,11**,1111,****11111111 d/B'[Ur
#M5_em4kN
这里有三点很重要: I#U>5"%\a
1.每个成员分别按自己的方式对齐,并能最小化长度 }pMP!%|
2.复杂类型(如结构)的默认对齐方式是它最长的成员的对齐方式,这样在成员是复杂类型时,可以最小化长度 %M{k.FE(
3.对齐后的长度必须是成员中最大的对齐参数的整数倍,这样在处理数组时可以保证每一项都边界对齐 WY+(]Wkao
~{kM5:-iw
9<|m4
网友xue23(xue23) 的答案和分析: @iU%`=ziz
&P
8!]:
有程序查一下各个变量的内存地址得知: r8uqcKfU
各个变量在内存中的位置为 W.A1m4l58R
c***aa** t`"^7YFS>
bbbb**** -@''[m .*
dddddddd =-$!:W~
测试代码为: ^
<qrM
s2 ss; CQdBf3q
cout << "ss.c = " << &ss << endl ; tTotPPZf}
cout << "ss.d.a = " <<&ss.d.a << endl; UvkJ?Bu
cout << "ss.d.b = " <<&(ss.d.b) < cout << "ss.d = " <<&ss.e << endl; 1GtOA3,~;-
print out 各个变量的内存地址不就可以看出来了吗。 07x=`7hs}
"~u_\STn <
所以答案是24,2. h|bqyu
,>;!%Ui/p
但是我的想像中应该是这样的分布情况: 24|
c******* T H|?X0b
aa**bbbb S|"Fgoj r
dddddddd fNkuX-om
(/"thv5vT{
不知为什么会c和a放在一起,组成8位长度。