Intel和微软同时出现的C语言面试题 @euH[<
#pragma pack(8) ppm=o4`s[
Zr(4Q9fDo
struct s1{ G3.*fSY$.<
short a; i2+r#Hw#5R
long b; ;C^!T
}; .j
et0w
$ol]G`+
struct s2{ _+sb~
char c;
%wFz4:
s1 d; }nEa9h
long long e; MQc<AfW3/
}; G_m $?0\
kC,=E9)O
#pragma pack() C33BP}c]
YYE{zU
问 o*k.je1
1.sizeof(s2) = ? jo-2D[Q{
2.s2的s1中的a后面空了几个字节接着是b? V),wDyi
~mF^t7n]
3# g"Z7/
@:dn\{Zsea
如果您知道答案请在讨论中写出,以下是部份网友的答案,供参考: k!Ym<RD%N
c;X%Ar
网友rwxybh(行云)的答案: X!b+Dk
内存布局是 0dTHF})m
1*** 11** #ORZk6e
1111 **** IdS=lN$
1111 1111 'iM#iA8
"L0Q"t:
所以答案就是24和3 (U{,D1?
Z5j\ M
下面是一个测试的程序,试一试就知道了,我用的是VC2005 [S~/lm
$+k|\+iJ
#pragma pack(8) +TZVx(Z&A
Af"p:;^z
struct s1{ v~*Co}0OB
short a; // 2 BYtes ~xa yGk
long b; // 4 Bytes 1^ijKn@6
}; a
Xn:hn~O
struct s2{ |Q(3rcOrV"
char c; // 1 Byte pqCp>BO?O
s1 d; // 8 Bytes xA'RO-a}h
long long e; // 8 Bytes :'
=le*h
}; ptc.JB6
// 1*** 11** 0$qK: ze
// 1111 **** dfA2G<Uc
// 1111 1111 :@RX}rKG
// dO1h1yJJ
,Y&7` m
// 00 01 02 03 04 05 06 07 l\/uXP?
// 00 01 02 03 04 05 06 07 j%U'mGx
// 00 01 02 03 04 05 06 07 ynZp|'b?<
// 1!%T<!A.
#pragma pack() zv-9z
Yu}[RXC(=
int main(int argc, char* argv[]) 4C#r=Uw`
{ eP|_
s2 a; yMz dM&a!*
char *p = (char *)&a; LE|DMz|J
for(int i=0;i<24;++i) Q\nIU7:bZ
p = (char)(i%8); @CtnV|
printf("%d\n",sizeof(a)); p)qM{`]G\
printf("c=0x%lx\n",a.c); 1`sTGNo
printf("d.a=0x%x\n",a.d.a); ,bxGd!&{Q
printf("d.b=0x%x\n",a.d.b); 4Uk\h gT0
printf("e=0x%llx\n",a.e); z j F'CY
return 0; ZBkbr
} XxY wBc'pc
结果: hAV@/oQ
24 dw-o71(1d
c=0x0 nb\pBl
d.a=0x504 H
-K%F_#
d.b=0x3020100 [ KDNKK
e=0x706050403020100 Z?<&@YQS
uhm3}mWv
JLbmh1'
网友 redleaves (ID最吊的网友)的答案和分析: (F j"<
0<XxR6w
如果代码: *7w,o?l
#pragma pack(8) lt("yqBu
struct S1{ "$n ff=]
char a; =D`:2k~
,
long b; eMLcmZJR
}; &X6hOc:``\
struct S2 { cX#U_U~d
char c; #Ibpf ,
struct S1 d; 8
KRo<
long long e; Zg4kO;r08
}; $!vK#8-&{
#pragma pack() z?Cez*.h>
sizeof(S2)结果为24. ;LC?3.
成员对齐有一个重要的条件,即每个成员分别对齐.即每个成员按自己的方式对齐. (@Kc(>(: Y
也就是说上面虽然指定了按8字节对齐,但并不是所有的成员都是以8字节对齐.其对齐的规则是,每个成员按其类型的对齐参数(通常是这个类型的大小)和指定对齐参数(这里是8字节)中较小的一个对齐.并且结构的长度必须为所用过的所有对齐参数的整数倍,不够就补空字节. p=[SDk`
aM4-quaG]
S1中,成员a是1字节默认按1字节对齐,指定对齐参数为8,这两个值中取1,a按1字节对齐;成员b是4个字节,默认是按4字节对齐,这时就按4字节对齐,所以sizeof(S1)应该为8; 4 'DEdx,&f
S2中,c和S1中的a一样,按1字节对齐,而d 是个结构,它是8个字节,它按什么对齐呢?对于结构来说,它的默认对齐方式就是它的所有成员使用的对齐参数中最大的一个,S1的就是4.所以,成员d就是按4字节对齐.成员e是8个字节,它是默认按8字节对齐,和指定的一样,所以它对到8字节的边界上,这时,已经使用了12个字节了,所以又添加了4个字节的空,从第16个字节开始放置成员e.这时,长度为24,已经可以被8(成员e按8字节对齐)整除.这样,一共使用了24个字节. 2@!B;6*8q
a b 48,uO!
S1的内存布局:11**,1111, 3ESrd"W=
c S1.a S1.b d iOtf7.@
S2的内存布局:1***,11**,1111,****11111111 U/A
[al
6@x^,SA
这里有三点很重要: @e-2]z
1.每个成员分别按自己的方式对齐,并能最小化长度 #]h&GX
2.复杂类型(如结构)的默认对齐方式是它最长的成员的对齐方式,这样在成员是复杂类型时,可以最小化长度 iHT=ROL
3.对齐后的长度必须是成员中最大的对齐参数的整数倍,这样在处理数组时可以保证每一项都边界对齐 -br): }f
C{>dE:*K^
fizL_`uMqb
网友xue23(xue23) 的答案和分析: iEx4va-j
o;u~Yg
有程序查一下各个变量的内存地址得知: **.g^Pyc
各个变量在内存中的位置为 AHU=`z
c***aa** PDS?>Jg(
bbbb**** cEIs9;
dddddddd c5Hyja=
测试代码为: TSH'OW !b
s2 ss; X.V4YmZ-;
cout << "ss.c = " << &ss << endl ; */OKg;IMi
cout << "ss.d.a = " <<&ss.d.a << endl; bZ#5\L2
cout << "ss.d.b = " <<&(ss.d.b) < cout << "ss.d = " <<&ss.e << endl; 6MpV,2:>
print out 各个变量的内存地址不就可以看出来了吗。 A*{CT>
+`ug?`_
所以答案是24,2. aP]h03sS
92ngSaNC
但是我的想像中应该是这样的分布情况: eVzZfB-=4}
c******* r%9=75HA
aa**bbbb Wjli(sT#-
dddddddd $|N\(}R
? ph>:M
不知为什么会c和a放在一起,组成8位长度。