Intel和微软同时出现的C语言面试题 3A0Qjj=
#pragma pack(8) XL44pE
m
`c^">L
struct s1{ [uJS.`b
short a; )x?)v#k
long b; =/xx:D/
}; mm*nXJ
`tuGy}S2
struct s2{ 4Q1R:Ra
char c; ,ExY.'%1
s1 d;
0,&] 2YJ
long long e; zgGJ<=G.
}; YADXXQ"
xEq? [M
#pragma pack() BbCW3!(
jrS$!cEo
问 :}q)]W
1.sizeof(s2) = ? M<=e~';H
2.s2的s1中的a后面空了几个字节接着是b? z[vu-f9
*Jt+-ZM
LEN=pqGJ.
/V2yLHm
如果您知道答案请在讨论中写出,以下是部份网友的答案,供参考: s^.tj41Gx}
fGA#0/_`
网友rwxybh(行云)的答案: y"8,j m
内存布局是 x
<aR|r
1*** 11** _V8;dv8
1111 **** -glGOTk
1111 1111 BhjDyB
BaUuDo/ZO
所以答案就是24和3 0k_3]Li=(
` PeC,bp
下面是一个测试的程序,试一试就知道了,我用的是VC2005 hpbi!g
6wbH{}\ll
#pragma pack(8) 3A =\Mb
.h/2-pQ>
struct s1{ S !lrnH
short a; // 2 BYtes lqO>Q1_{K
long b; // 4 Bytes A@Zqh<,Ud
}; <Voct
struct s2{ WuI$
char c; // 1 Byte A5\ Hq
s1 d; // 8 Bytes xh#pw2v7V
long long e; // 8 Bytes p/l">d]+
}; >[nR$8_J-l
// 1*** 11** g-ZXj4Ph!
// 1111 ****
V_e
// 1111 1111 RU/SJ1wM"
// (!efaj
TI2K_'
// 00 01 02 03 04 05 06 07 4MzPm~Ct
// 00 01 02 03 04 05 06 07 }}rp/16
// 00 01 02 03 04 05 06 07 j0Cj&x%qF}
// tv~Y5e&8
#pragma pack() oxUBlye
t.\Pn4
int main(int argc, char* argv[]) eR`Q7]j] -
{ CGb4C(%-7
s2 a; c4Q9foE
char *p = (char *)&a; Eg}U.ss^
for(int i=0;i<24;++i) SjF(;0kC
p = (char)(i%8); 1*6xFn
printf("%d\n",sizeof(a)); 9&6P,ts%Q
printf("c=0x%lx\n",a.c); H?ug-7k/
printf("d.a=0x%x\n",a.d.a); YRv96|c,
printf("d.b=0x%x\n",a.d.b); pp{p4Z
printf("e=0x%llx\n",a.e); V[Sj+&e&
return 0; +7AH|v8
} CY*GCkH
结果: <$Sl%DoS
24 O.\\)8xA
c=0x0 4#:Eq=(W
d.a=0x504 8\C][ y
d.b=0x3020100 _ShWCU-~Z
e=0x706050403020100 DSq?|H
@,2,(=l*C
D#`>p
网友 redleaves (ID最吊的网友)的答案和分析: 0%q H=do6
v046
如果代码: -0]%#(E%`h
#pragma pack(8) 9KJ}Ai
struct S1{ 62Tel4u
char a; ,)TnIByM
long b; %]4=D)Om
}; jY=M{?h''
struct S2 { i]4n YYS
char c; ~J5B?@2hK
struct S1 d; je 3Qq1
long long e; m],.w M8
}; Bu?Qyz2O
#pragma pack() E'6/@xM
sizeof(S2)结果为24. {.;qz4d`
成员对齐有一个重要的条件,即每个成员分别对齐.即每个成员按自己的方式对齐. hM>.xr
也就是说上面虽然指定了按8字节对齐,但并不是所有的成员都是以8字节对齐.其对齐的规则是,每个成员按其类型的对齐参数(通常是这个类型的大小)和指定对齐参数(这里是8字节)中较小的一个对齐.并且结构的长度必须为所用过的所有对齐参数的整数倍,不够就补空字节. N_Zd.VnY
%~>-nqS
S1中,成员a是1字节默认按1字节对齐,指定对齐参数为8,这两个值中取1,a按1字节对齐;成员b是4个字节,默认是按4字节对齐,这时就按4字节对齐,所以sizeof(S1)应该为8; E`C!q
X>
S2中,c和S1中的a一样,按1字节对齐,而d 是个结构,它是8个字节,它按什么对齐呢?对于结构来说,它的默认对齐方式就是它的所有成员使用的对齐参数中最大的一个,S1的就是4.所以,成员d就是按4字节对齐.成员e是8个字节,它是默认按8字节对齐,和指定的一样,所以它对到8字节的边界上,这时,已经使用了12个字节了,所以又添加了4个字节的空,从第16个字节开始放置成员e.这时,长度为24,已经可以被8(成员e按8字节对齐)整除.这样,一共使用了24个字节. w-NTw2x,&
a b Tdz#,]Q
S1的内存布局:11**,1111, 5DkEJk7a
c S1.a S1.b d "3a}~J<g
S2的内存布局:1***,11**,1111,****11111111 ?|
6sTu!
-okq=9
这里有三点很重要: *DZ7,$LQ~D
1.每个成员分别按自己的方式对齐,并能最小化长度 \}Iq-Je
2.复杂类型(如结构)的默认对齐方式是它最长的成员的对齐方式,这样在成员是复杂类型时,可以最小化长度 Y7I\<JG<
3.对齐后的长度必须是成员中最大的对齐参数的整数倍,这样在处理数组时可以保证每一项都边界对齐 5Fj9.K~k
Dbq/t^
2|WM?V&
网友xue23(xue23) 的答案和分析: X8R:9q_
59"tHb6 E
有程序查一下各个变量的内存地址得知: 7|_2@4-W6
各个变量在内存中的位置为 3-1a+7fD
c***aa** .j>MsQP#\C
bbbb**** rO{?.#~
dddddddd 8Z"f"
测试代码为: 5v`lCu]
s2 ss; :)T*:51{#
cout << "ss.c = " << &ss << endl ; 8K8jz9.s
cout << "ss.d.a = " <<&ss.d.a << endl; R?tjobk!
cout << "ss.d.b = " <<&(ss.d.b) < cout << "ss.d = " <<&ss.e << endl; + 660/ e8N
print out 各个变量的内存地址不就可以看出来了吗。 (ov&iNx
mI:^lp
所以答案是24,2. R7!v=X]i
M`@AS L:u
但是我的想像中应该是这样的分布情况: Xh3b=i|K
c******* z}7}D !
aa**bbbb CPeu="[
dddddddd NpKyrXDJv
H5
:,hrZY
不知为什么会c和a放在一起,组成8位长度。