Intel和微软同时出现的C语言面试题 gq:2`W&5
#pragma pack(8) bb@3%r|_<
aRc2#:~;
struct s1{ @hz~9AII9
short a; V\2&?#GZ
long b; qs U ob
}; 2k}8`P;
7'Y 3T[
struct s2{ su/l'p'
char c; BusD}9QqB
s1 d; Gp'rN}i^
long long e; gN$.2+:
}; 7kx)/Rw\B
cOcF VPQ
#pragma pack() p;`jmF
z8{ kwz
问 trnjOm
1.sizeof(s2) = ? &Z/aM?
2.s2的s1中的a后面空了几个字节接着是b? !}|n3wQ
xCFk1%qf
<KqZ.7XfB
DvHcT]l>5
如果您知道答案请在讨论中写出,以下是部份网友的答案,供参考: $UavM|
9KRHo%m
网友rwxybh(行云)的答案: TKj8a(R_
内存布局是 K,bv\j;f
1*** 11** UhYeyT
1111 **** x$d3fsEE
1111 1111 I!&|L0Qq
)9MmL-7K
所以答案就是24和3 T^g2N`w2
R nt&<|8G
下面是一个测试的程序,试一试就知道了,我用的是VC2005 6js94ko[
8o#*0d|
#pragma pack(8) B
=@BYqiY
}tv%
struct s1{ *gfx'$
short a; // 2 BYtes zQM3n =y
long b; // 4 Bytes ce th )Xm
}; BM!\U 6
struct s2{ G[n^SEY!
char c; // 1 Byte 0"7xCx
s1 d; // 8 Bytes e^Q$Tog<
long long e; // 8 Bytes y`wTw/5N
}; CwZ+Pn0
// 1*** 11** =)vmX0vL
// 1111 ****
(M5w:qbR
// 1111 1111 ,IoPK!5xy
// T{3C3EE?]
5A /8G}'XZ
// 00 01 02 03 04 05 06 07 EKoAIC*?p
// 00 01 02 03 04 05 06 07 ac"Pn?
q
// 00 01 02 03 04 05 06 07 VXXo\LQUU
// l|z
'Lwwm5
#pragma pack() ?9xaBWf
?F]Yebp^
int main(int argc, char* argv[]) Xd/gvg{??0
{ \GS]jhEtn
s2 a; (G $nN*rlu
char *p = (char *)&a; aKXaor@0f.
for(int i=0;i<24;++i) Nq6~6Rr
p = (char)(i%8); A]"$O&l
printf("%d\n",sizeof(a)); opxVxjTT#
printf("c=0x%lx\n",a.c); S%gb1's
printf("d.a=0x%x\n",a.d.a); 5_Yl!=
printf("d.b=0x%x\n",a.d.b); 2*Hw6@Jj
printf("e=0x%llx\n",a.e); BTjfzfO"
return 0; 8"/5Lh(
} }ozlED`E
结果: ;> **+ezF
24
/B)ZB})z
c=0x0 H6(kxpOI\
d.a=0x504 oVutHt
d.b=0x3020100 gXN#<g,:^
e=0x706050403020100 ]Aap4+s
hNs970i
D,%R[F?5O
网友 redleaves (ID最吊的网友)的答案和分析: g\;AU2?p7
3kFSu
如果代码: w^MU$ubx
#pragma pack(8) }MAQhXI^O|
struct S1{ ufAp7m@ud
char a; =<w6yeko
long b; d!kiWmw,
}; 6,
\i0y5n
struct S2 { JR{3n*
char c; <Z5ak4P
struct S1 d; KD?~ hpg
long long e; `l,=iy$
}; 6}^0/76^,
#pragma pack() d2lOx|jt
sizeof(S2)结果为24. 4<._)_m
成员对齐有一个重要的条件,即每个成员分别对齐.即每个成员按自己的方式对齐. oR (hL4Dc
也就是说上面虽然指定了按8字节对齐,但并不是所有的成员都是以8字节对齐.其对齐的规则是,每个成员按其类型的对齐参数(通常是这个类型的大小)和指定对齐参数(这里是8字节)中较小的一个对齐.并且结构的长度必须为所用过的所有对齐参数的整数倍,不够就补空字节. v(D{_
AujvKQ(
S1中,成员a是1字节默认按1字节对齐,指定对齐参数为8,这两个值中取1,a按1字节对齐;成员b是4个字节,默认是按4字节对齐,这时就按4字节对齐,所以sizeof(S1)应该为8; HL$}Gh]q
S2中,c和S1中的a一样,按1字节对齐,而d 是个结构,它是8个字节,它按什么对齐呢?对于结构来说,它的默认对齐方式就是它的所有成员使用的对齐参数中最大的一个,S1的就是4.所以,成员d就是按4字节对齐.成员e是8个字节,它是默认按8字节对齐,和指定的一样,所以它对到8字节的边界上,这时,已经使用了12个字节了,所以又添加了4个字节的空,从第16个字节开始放置成员e.这时,长度为24,已经可以被8(成员e按8字节对齐)整除.这样,一共使用了24个字节. ._@Scd
a b vWY}+#
S1的内存布局:11**,1111, BE. v+'c"
c S1.a S1.b d i0DYdUj
S2的内存布局:1***,11**,1111,****11111111 1];rW`Bw
N"MK 0k
这里有三点很重要: EeGP E
1.每个成员分别按自己的方式对齐,并能最小化长度 ModwJ
w
2.复杂类型(如结构)的默认对齐方式是它最长的成员的对齐方式,这样在成员是复杂类型时,可以最小化长度 c#sPM!!
3.对齐后的长度必须是成员中最大的对齐参数的整数倍,这样在处理数组时可以保证每一项都边界对齐 z3+y|nx!
AY4ZU CqI
Q!K@
网友xue23(xue23) 的答案和分析: YSwAu,$jf
!Cxo4Twg
有程序查一下各个变量的内存地址得知: wHm{4
各个变量在内存中的位置为 LX),oR
c***aa** XH4!|wz
bbbb**** `&$"oW{HW
dddddddd )1ia;6}
测试代码为: 7[5g_D t
s2 ss; Gxu
cout << "ss.c = " << &ss << endl ; 2|]$hjs
cout << "ss.d.a = " <<&ss.d.a << endl; -y]\;pbZ0
cout << "ss.d.b = " <<&(ss.d.b) < cout << "ss.d = " <<&ss.e << endl; N%N%
print out 各个变量的内存地址不就可以看出来了吗。 f!hQ"1[
L6`(YX.:
所以答案是24,2. tiG=KHK%o
NIufL
}6\
但是我的想像中应该是这样的分布情况: cF!ygz//
c******* ]oB-qfbH
aa**bbbb i? 5jl&30
dddddddd xCwd*lsM
+c4]}9f!
不知为什么会c和a放在一起,组成8位长度。