Intel和微软同时出现的C语言面试题 o78u>O y
#pragma pack(8) N'{[BA(eE
O|Uz)Y94
struct s1{ c5]Xqq,
short a; ~${~To8$CW
long b; OG$n C
}; "'4
j6%W+;{/pj
struct s2{ Q-x>yau"
char c; #X Q/y} (
s1 d; ^s~)"2 g
long long e; "GMU~594
}; ZP";B^J
<83Ky;ry
#pragma pack() ~ l}f@@u
!y_FbJ8KC
问 9xA4;)36
1.sizeof(s2) = ? Hf4_zd
2.s2的s1中的a后面空了几个字节接着是b? o30C\
}`=7%b`-?
P2n8H Fi
TdFU,
如果您知道答案请在讨论中写出,以下是部份网友的答案,供参考: IQ_6DF
; Y/nS
网友rwxybh(行云)的答案: j!+jLm!l
内存布局是 %q5dV<X'c
1*** 11** [,;Y5#Y[5
1111 **** !*]i3 ,{7v
1111 1111 4DL;Y
7hJX
所以答案就是24和3 yaz6?,)
Yxq!7J
下面是一个测试的程序,试一试就知道了,我用的是VC2005 ~n=DI/AJ@-
2u.0AG
#pragma pack(8) ^ITF*
$J1`.Q>)4
struct s1{ rHKO13WF
short a; // 2 BYtes d(IJ-qJN
long b; // 4 Bytes il^;2`]&
}; ("U<@~
struct s2{ JrcbJt
char c; // 1 Byte b1Vr>:sK47
s1 d; // 8 Bytes 4,y7a=qf3
long long e; // 8 Bytes f*%kHfaXgN
}; !Yof%%m$;
// 1*** 11** X>I3N?5
// 1111 **** U["0B8
// 1111 1111 r+#{\~r7T
// x2v0cR"KL
y[N0P0r l:
// 00 01 02 03 04 05 06 07 )rEl{a
// 00 01 02 03 04 05 06 07 Y` }X5(A@
// 00 01 02 03 04 05 06 07 @i#JlZM_
// B:h<iU:'D
#pragma pack() |_?e.}K
HOx4FXPs
int main(int argc, char* argv[]) oq7G=8gTp
{ C1^%!)
s2 a; a0NiVF-m%
char *p = (char *)&a; jG>W+lq
for(int i=0;i<24;++i) Zn9tG:V
p = (char)(i%8); 8-#kY}d.
printf("%d\n",sizeof(a)); 3ijPm<wn
printf("c=0x%lx\n",a.c); !hVbx#bXl
printf("d.a=0x%x\n",a.d.a); oC`F1!SfOO
printf("d.b=0x%x\n",a.d.b); :M(uP e=D
printf("e=0x%llx\n",a.e); Sp>g77@
return 0; (MLcA\LJ
} t:2DB)
结果: $udhTI#,
24 44KoOY_
c=0x0 N3"Jo uP
d.a=0x504 <0d2{RQ;
d.b=0x3020100 g}MUfl-L
e=0x706050403020100 tWn
dAM(U7
a&>NuMDI
QIiy\E%
网友 redleaves (ID最吊的网友)的答案和分析: SnE^\I^O
?^voA.Bv<
如果代码: d,GOP_N8I
#pragma pack(8) "3^tVX%$\[
struct S1{ 9FDu{4:
char a; vRe{B7}p;
long b; F! =l
r
}; +W4}&S
struct S2 { OZ\6qMH3e
char c; #Hrzk!&9
struct S1 d; Mj;V.Y
long long e; H,} &=SCk
}; W6<oy
#pragma pack() F! !HwI
sizeof(S2)结果为24. >!Yuef
<P
成员对齐有一个重要的条件,即每个成员分别对齐.即每个成员按自己的方式对齐. Cd*h4Q]S
也就是说上面虽然指定了按8字节对齐,但并不是所有的成员都是以8字节对齐.其对齐的规则是,每个成员按其类型的对齐参数(通常是这个类型的大小)和指定对齐参数(这里是8字节)中较小的一个对齐.并且结构的长度必须为所用过的所有对齐参数的整数倍,不够就补空字节. %:aXEjm@
3}nk9S:jr
S1中,成员a是1字节默认按1字节对齐,指定对齐参数为8,这两个值中取1,a按1字节对齐;成员b是4个字节,默认是按4字节对齐,这时就按4字节对齐,所以sizeof(S1)应该为8; 0O"W0s"T#
S2中,c和S1中的a一样,按1字节对齐,而d 是个结构,它是8个字节,它按什么对齐呢?对于结构来说,它的默认对齐方式就是它的所有成员使用的对齐参数中最大的一个,S1的就是4.所以,成员d就是按4字节对齐.成员e是8个字节,它是默认按8字节对齐,和指定的一样,所以它对到8字节的边界上,这时,已经使用了12个字节了,所以又添加了4个字节的空,从第16个字节开始放置成员e.这时,长度为24,已经可以被8(成员e按8字节对齐)整除.这样,一共使用了24个字节. o*Qa*<n
a b ?=&; A
S1的内存布局:11**,1111, oPi>]#X
c S1.a S1.b d 1Ms]\<^j
S2的内存布局:1***,11**,1111,****11111111 $z=%e#(!I
7}&:07U
这里有三点很重要: _:Qh1 &h
1.每个成员分别按自己的方式对齐,并能最小化长度 krfXvQJwJ
2.复杂类型(如结构)的默认对齐方式是它最长的成员的对齐方式,这样在成员是复杂类型时,可以最小化长度 .D W>c}1
3.对齐后的长度必须是成员中最大的对齐参数的整数倍,这样在处理数组时可以保证每一项都边界对齐 o-6d$c}{f
v@zi?D K
BpIyw
网友xue23(xue23) 的答案和分析: 4]r_K2.cc
H9)@q3<
有程序查一下各个变量的内存地址得知: PCl5,]B}
各个变量在内存中的位置为 ~xd?y*gk;
c***aa** 9[/0
bbbb**** k|-\[Yl .
dddddddd 6\8d6x>
测试代码为: +Kk1[fh-
s2 ss; cK'g2S
cout << "ss.c = " << &ss << endl ; ! VR&HEru
cout << "ss.d.a = " <<&ss.d.a << endl; [1rQ'FBB^1
cout << "ss.d.b = " <<&(ss.d.b) < cout << "ss.d = " <<&ss.e << endl; =muQ7l:(
print out 各个变量的内存地址不就可以看出来了吗。 "'CvB0>
z>PVv)X
所以答案是24,2. =\6)B{#T
,'
k?rQ
但是我的想像中应该是这样的分布情况: e)uC
c******* Dck/Ea
aa**bbbb aEN` `
dddddddd t9`{^<LH
/1EAj
不知为什么会c和a放在一起,组成8位长度。