Intel和微软同时出现的C语言面试题 ~_Q1+ax}
#pragma pack(8) y ZR\(\?<
Z@{e\sZ)
struct s1{ d\A!5/LG
short a; ),]XN#jp(u
long b; g|rbkK%SoE
}; :B"Y3~I
9L9+zs3k
struct s2{ On4tK\l@
char c; TIre,s)_
s1 d; f15f)P
long long e; 1a>TJdoa
}; Q%
LQP!Kg
UUaC@Rs2
#pragma pack() y=spD^tM8
1^_V8dm)
问 yV/A%y-P
1.sizeof(s2) = ? C)xM>M_CB
2.s2的s1中的a后面空了几个字节接着是b? [/IN820t
z}&JapJ
MclW!CmJ
$PE{}`#g
如果您知道答案请在讨论中写出,以下是部份网友的答案,供参考: 5svM3 #
Ir :y#
网友rwxybh(行云)的答案: nb ,+!)+
内存布局是 %AnqT|\#,
1*** 11** :#&Y
1111 **** ;>Q.r{P
1111 1111 T.x"a$AU
HHcWyu
所以答案就是24和3 oQ"J>`',
Z %\*\6L)
下面是一个测试的程序,试一试就知道了,我用的是VC2005 -J\R}9 lIm
4J${gcju
#pragma pack(8) 5
i;n:&Y
L>.*^]
struct s1{ UG:S! w'
short a; // 2 BYtes na,i(m?l
long b; // 4 Bytes TM2pE/P
}; %6eQ;Rp*
struct s2{ h1+lVAQbT
char c; // 1 Byte E[kf%\
s1 d; // 8 Bytes 0` \!O(jJ
long long e; // 8 Bytes dAkJ5\=*
}; 6< O|,7=_
// 1*** 11** 0JS#{EDh+
// 1111 **** O{w'i|
// 1111 1111 eB,eu4+-
// ?vr9l7VOi
D +Ui1h-
// 00 01 02 03 04 05 06 07 w:+wx/\
// 00 01 02 03 04 05 06 07 I' TprT
// 00 01 02 03 04 05 06 07 asd3J
// Xah-*]ET
#pragma pack() M:QM*?+)
3yp?|>e
int main(int argc, char* argv[]) &x>8
%Q s
{ &2\^S+4
s2 a; LL"c 9jb4z
char *p = (char *)&a; Cr#Z.
for(int i=0;i<24;++i) i^2-PKPg{
p = (char)(i%8); ^DH*\ee
printf("%d\n",sizeof(a)); t+<?$I[
printf("c=0x%lx\n",a.c); yirQ
printf("d.a=0x%x\n",a.d.a); 9w:9XziT
printf("d.b=0x%x\n",a.d.b); bj$VYS"kY
printf("e=0x%llx\n",a.e); c|KN@)A
return 0; ?4A$9H
} z(g6$Y{
结果: uXkc07 r'
24 F\IJim-Rh
c=0x0 hF;TX.Y6
d.a=0x504 V~!lY\
d.b=0x3020100 6<qVeO&uZ
e=0x706050403020100 QK0-jYG^
Oi-=
Fp
ngI3.v/R
网友 redleaves (ID最吊的网友)的答案和分析: cypb6Q_
ZW)_dg 9
如果代码: -gK*&n~
#pragma pack(8) n1J;)VyR
struct S1{ }$E341@
char a; =s5g9n+7
long b; ;VW->ia6
}; nC 2e^=^
struct S2 { &&$,BFY4
char c; ,!7\?=G6}v
struct S1 d; Pg\!\5
long long e; fv+t%,++:
}; {#C)S&o)6
#pragma pack() 5[5|_H+0
sizeof(S2)结果为24. 0LD$"0v/C3
成员对齐有一个重要的条件,即每个成员分别对齐.即每个成员按自己的方式对齐. K2
b\9}
也就是说上面虽然指定了按8字节对齐,但并不是所有的成员都是以8字节对齐.其对齐的规则是,每个成员按其类型的对齐参数(通常是这个类型的大小)和指定对齐参数(这里是8字节)中较小的一个对齐.并且结构的长度必须为所用过的所有对齐参数的整数倍,不够就补空字节. Uuq*;L
n3B#M}R
S1中,成员a是1字节默认按1字节对齐,指定对齐参数为8,这两个值中取1,a按1字节对齐;成员b是4个字节,默认是按4字节对齐,这时就按4字节对齐,所以sizeof(S1)应该为8; kX)QHNzP
S2中,c和S1中的a一样,按1字节对齐,而d 是个结构,它是8个字节,它按什么对齐呢?对于结构来说,它的默认对齐方式就是它的所有成员使用的对齐参数中最大的一个,S1的就是4.所以,成员d就是按4字节对齐.成员e是8个字节,它是默认按8字节对齐,和指定的一样,所以它对到8字节的边界上,这时,已经使用了12个字节了,所以又添加了4个字节的空,从第16个字节开始放置成员e.这时,长度为24,已经可以被8(成员e按8字节对齐)整除.这样,一共使用了24个字节. .mwB'Ll
a b +]dh`8*8>1
S1的内存布局:11**,1111, &$L6*+`h#
c S1.a S1.b d N3$%!\~O
S2的内存布局:1***,11**,1111,****11111111 J@l QzRqRb
"eG@F
这里有三点很重要: A-*y[/
1.每个成员分别按自己的方式对齐,并能最小化长度 2PTAIm Rq
2.复杂类型(如结构)的默认对齐方式是它最长的成员的对齐方式,这样在成员是复杂类型时,可以最小化长度 #_?m.~`g[
3.对齐后的长度必须是成员中最大的对齐参数的整数倍,这样在处理数组时可以保证每一项都边界对齐 aPRXK1
%|AXVv7IN>
VV$4NV&`Q
网友xue23(xue23) 的答案和分析: \qZ>WCp>r
J{qsCJiB
有程序查一下各个变量的内存地址得知: pr?k~Bn
各个变量在内存中的位置为 ;]\>jC
c***aa** $/#F9>eZ
bbbb**** rm?C_
dddddddd UVlh7w jg
测试代码为: 8_:j.(n
s2 ss; Jk>!I\
cout << "ss.c = " << &ss << endl ; G<:gNWXd\
cout << "ss.d.a = " <<&ss.d.a << endl; `)WC|= w2
cout << "ss.d.b = " <<&(ss.d.b) < cout << "ss.d = " <<&ss.e << endl; Rx,5?*b$
print out 各个变量的内存地址不就可以看出来了吗。 g)L<xN8
[M/0 Qx[,
所以答案是24,2. ;m#_Rj6
?mn&b G
但是我的想像中应该是这样的分布情况: 57(5+Zme
c******* =lZtI6tZ
aa**bbbb ,Z$!:U
dddddddd Y5z5LG4
|A, <m#C
不知为什么会c和a放在一起,组成8位长度。