Intel和微软同时出现的C语言面试题 Q)\4 .d
#pragma pack(8) IkJ-*vI6
/~;om\7r
struct s1{ a}/ A]mu
short a; di]TS9&9
long b; /}$D&KwYg
}; ~k'SP(6#C
J`d;I#R%c
struct s2{ Hn!13+fS
char c; yk&PJ;%O<
s1 d; ~-o[v-\
long long e; jS| 9jg:
}; (E]q>'X
3/0E9'
#pragma pack() 2N[/Cc2Tg/
6ly`lu9
问 ='<789wT
1.sizeof(s2) = ? =/MA`>
2.s2的s1中的a后面空了几个字节接着是b? Iju9#b6
^K'@W
D
$3Mg
Q?]-/v
如果您知道答案请在讨论中写出,以下是部份网友的答案,供参考: GEUC<bL+
j NkobJ1
网友rwxybh(行云)的答案: Y2Y)| <FH
内存布局是 z6;6 o!ej
1*** 11** B6xM#)
1111 **** G#nZ%qQ:I
1111 1111 JBt2R=
u@pimRVo
所以答案就是24和3 .6[7D
0<#>LWaM_
下面是一个测试的程序,试一试就知道了,我用的是VC2005 p;n"zr8U
+Fa!<txn
#pragma pack(8) JK'FJ}Z4
1V:I}~\
struct s1{ S^T
><C
short a; // 2 BYtes Z|$M 9E
long b; // 4 Bytes hU6oWm
}; ;9$71E
struct s2{ a|eHo%Qt
char c; // 1 Byte &OsO _F
s1 d; // 8 Bytes #Ic)]0L
long long e; // 8 Bytes w?:tce
}; zv0bE?W9
// 1*** 11** _9:r4|S
// 1111 **** 7BkY0_KK
// 1111 1111 7!U^?0?/
// F<TIZ^gFP
:T )R;E@
// 00 01 02 03 04 05 06 07 Ake@krh>$
// 00 01 02 03 04 05 06 07 5yk#(i7C
// 00 01 02 03 04 05 06 07 ZXl_cq2r
// %%FzBbWAO
#pragma pack() LS]0 p#
Q@KCODi
int main(int argc, char* argv[]) y#zO1Nig`
{ Kv9Z.DY
s2 a; T:Nc^QP|tm
char *p = (char *)&a; f~ wgMp.W0
for(int i=0;i<24;++i) uH]oHh!}j
p = (char)(i%8); -nXlW
printf("%d\n",sizeof(a)); F:N8{puq5
printf("c=0x%lx\n",a.c); 7@
\:l~{
printf("d.a=0x%x\n",a.d.a); stQ_Ke
printf("d.b=0x%x\n",a.d.b); C),i#v
printf("e=0x%llx\n",a.e); -}_1f[b
return 0; h:RP/0E
} y*%uGG5
结果: LUdXAi"f
24 R$X~d8o>%
c=0x0 eG7Yyz+t$
d.a=0x504 }O Y/0p-Z
d.b=0x3020100 0X3yfrim
e=0x706050403020100 BP}@E$
~7anj.
ocu,qL)W
网友 redleaves (ID最吊的网友)的答案和分析: LcZ|A;it
T'{9!By,P
如果代码: |az2vD6P
#pragma pack(8) ,u>[cRqw
struct S1{ Ol~M
BQs
char a; 2RQ-L
long b; PMUW<UI
}; &d0sv5&s
struct S2 { gB~^dv {
char c; s VHk;:e>x
struct S1 d; c]zFZJ6M
long long e; NBHpM}1xtU
}; <{GVA0nr
#pragma pack() [dAQrou6P
sizeof(S2)结果为24. ^qnmKA>"F
成员对齐有一个重要的条件,即每个成员分别对齐.即每个成员按自己的方式对齐. "Kdn`zN{
也就是说上面虽然指定了按8字节对齐,但并不是所有的成员都是以8字节对齐.其对齐的规则是,每个成员按其类型的对齐参数(通常是这个类型的大小)和指定对齐参数(这里是8字节)中较小的一个对齐.并且结构的长度必须为所用过的所有对齐参数的整数倍,不够就补空字节. $xWUzg1<U
,yA[XAz~U
S1中,成员a是1字节默认按1字节对齐,指定对齐参数为8,这两个值中取1,a按1字节对齐;成员b是4个字节,默认是按4字节对齐,这时就按4字节对齐,所以sizeof(S1)应该为8; k/D{&(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个字节. J>5 rkR@/
a b aL%E#
S1的内存布局:11**,1111, %IZd-N7i^
c S1.a S1.b d k%FA:ms|k
S2的内存布局:1***,11**,1111,****11111111 vFB^h1k~.M
s M*ay,v;
这里有三点很重要: r0 )ne|&Hp
1.每个成员分别按自己的方式对齐,并能最小化长度 xP!QV~$>
2.复杂类型(如结构)的默认对齐方式是它最长的成员的对齐方式,这样在成员是复杂类型时,可以最小化长度 A&bj l[s
3.对齐后的长度必须是成员中最大的对齐参数的整数倍,这样在处理数组时可以保证每一项都边界对齐 U8AH,?]#
!nCq8~#
PO?_i>mA
网友xue23(xue23) 的答案和分析: 5|nc^
12
fum.G{}
有程序查一下各个变量的内存地址得知: r34MDUZdI
各个变量在内存中的位置为 )9:5?,SO
c***aa** Q{RmE:
bbbb**** )+hV+rM jp
dddddddd (Xcy/QT
测试代码为: 7oWMjw\
s2 ss; VOLj#H
cout << "ss.c = " << &ss << endl ; -X~mW
cout << "ss.d.a = " <<&ss.d.a << endl; 18!y7
_cFT
cout << "ss.d.b = " <<&(ss.d.b) < cout << "ss.d = " <<&ss.e << endl; ?)y^ [9
print out 各个变量的内存地址不就可以看出来了吗。 !~Uj 'w
}}{n|l+R5
所以答案是24,2. GD{L$#i!
=i&,I{3
但是我的想像中应该是这样的分布情况: o[T+/Ej&
c******* e[fOm0^.c
aa**bbbb 1XMR7liE
dddddddd <"J]u@|
jk{(o09
不知为什么会c和a放在一起,组成8位长度。