Intel和微软同时出现的C语言面试题 ("0@_05OH
#pragma pack(8) T=35?
ZKzXSI4
struct s1{ :*gYzk8
short a; aehGT|
long b; m(>_C~rGN
}; Xt~`EN
4o8uWS{`
struct s2{ 5W"nn
char c; mA}-hR%
s1 d; Q}FDu,
long long e; i/9QOw~
}; )W95)]
Q];gC{I
#pragma pack() MzT#1~
\?c0XD
问 ^8$CpAK]M
1.sizeof(s2) = ? ]y3V^W#
2.s2的s1中的a后面空了几个字节接着是b? RmxgCe(2a
pW7vY)hj
K&0op 4&
N]R<EBq
如果您知道答案请在讨论中写出,以下是部份网友的答案,供参考: Gc>bli<-
ez=$ ]cln
网友rwxybh(行云)的答案: [?x9NQ{
内存布局是 ?z% @;&
1*** 11** 9 P_`IsVK
1111 **** hO(8v&ns3
1111 1111 lA {
_/ bF t6
所以答案就是24和3 ^0"NcOzzxl
zqfv|3-!}
下面是一个测试的程序,试一试就知道了,我用的是VC2005 DrLNY"Zq
}1]/dCv
#pragma pack(8) $T{,3;kt
*6^|i}
struct s1{ 3#huC=zbf
short a; // 2 BYtes >C y
long b; // 4 Bytes 0l3v>ty
}; 9;2PoW8
struct s2{ vl*CU"4
char c; // 1 Byte
RR!(,j^M
s1 d; // 8 Bytes eT1b88_
long long e; // 8 Bytes `}.K@17
}; h=SQ]nV{
// 1*** 11** }[}u5T`w>
// 1111 **** 0cZyO$.
// 1111 1111 dl;~-'0
// v'Ce|.;
*F* c
// 00 01 02 03 04 05 06 07 D5fJuT-bp
// 00 01 02 03 04 05 06 07 W/ZmG]sZE
// 00 01 02 03 04 05 06 07 H=])o21
// !R;P"%PHV
#pragma pack() '#$Y:/
C\Q3vG
int main(int argc, char* argv[]) jcHs!
{ <J-bDcp
s2 a; 6TJ5G8z_
char *p = (char *)&a; &B^#?vmO
for(int i=0;i<24;++i) )#k*K9[@
p = (char)(i%8); =BQM(mal
printf("%d\n",sizeof(a)); (A O]f fBU
printf("c=0x%lx\n",a.c); ,/6V ^K
printf("d.a=0x%x\n",a.d.a); r9z_8#cR
printf("d.b=0x%x\n",a.d.b); 6~zR(HzV{
printf("e=0x%llx\n",a.e); ,\!4A
return 0; 7IW:,=Zk8+
} ;'l Hw]}O*
结果: EJ{Z0R{{
24 Ze~$by|9f
c=0x0 B+S
&vV
d.a=0x504 5w"f.d'
d.b=0x3020100 ]\5@N7h
e=0x706050403020100 )V~Fl$A
.z&V!2zp
m76**X
网友 redleaves (ID最吊的网友)的答案和分析: 6g4CUP'Y
2Fi>nJ
如果代码: 0/hX3h
#pragma pack(8) *I%r
struct S1{ jC+>^=J(
char a; SjD,
long b; iY"I:1l.
}; mN+~fuh
struct S2 { j[NA3Vj1P
char c; {Uxah
struct S1 d; QwXM<qG*
long long e; Hn)K;?H4
}; ! P/ ]o
#pragma pack() =<fH RX`
sizeof(S2)结果为24. H6E@C}cyM
成员对齐有一个重要的条件,即每个成员分别对齐.即每个成员按自己的方式对齐. *}R5=r0
也就是说上面虽然指定了按8字节对齐,但并不是所有的成员都是以8字节对齐.其对齐的规则是,每个成员按其类型的对齐参数(通常是这个类型的大小)和指定对齐参数(这里是8字节)中较小的一个对齐.并且结构的长度必须为所用过的所有对齐参数的整数倍,不够就补空字节. lnL&v'{
9qD/q?Hh$
S1中,成员a是1字节默认按1字节对齐,指定对齐参数为8,这两个值中取1,a按1字节对齐;成员b是4个字节,默认是按4字节对齐,这时就按4字节对齐,所以sizeof(S1)应该为8; ~ z4T
S2中,c和S1中的a一样,按1字节对齐,而d 是个结构,它是8个字节,它按什么对齐呢?对于结构来说,它的默认对齐方式就是它的所有成员使用的对齐参数中最大的一个,S1的就是4.所以,成员d就是按4字节对齐.成员e是8个字节,它是默认按8字节对齐,和指定的一样,所以它对到8字节的边界上,这时,已经使用了12个字节了,所以又添加了4个字节的空,从第16个字节开始放置成员e.这时,长度为24,已经可以被8(成员e按8字节对齐)整除.这样,一共使用了24个字节. v:1l2Y)g
a b 58zs%+F
S1的内存布局:11**,1111, ZiM#g1;
c S1.a S1.b d AE!WYE
S2的内存布局:1***,11**,1111,****11111111 LinARMPv
PbxuD*LQ.
这里有三点很重要: .O @bX)
1.每个成员分别按自己的方式对齐,并能最小化长度 G}ElQD
2.复杂类型(如结构)的默认对齐方式是它最长的成员的对齐方式,这样在成员是复杂类型时,可以最小化长度 `%AFKmc^;
3.对齐后的长度必须是成员中最大的对齐参数的整数倍,这样在处理数组时可以保证每一项都边界对齐 |57KTiiNLI
/{ YUM~
>0)E\_ u
网友xue23(xue23) 的答案和分析: @v_E'
9QG^
w8:F^{
有程序查一下各个变量的内存地址得知: 5~k-c Ua
各个变量在内存中的位置为 :}x\&]uC#k
c***aa** i,rP/A^q
bbbb****
Y<TlvB)w
dddddddd udtsq"U_%
测试代码为: X@Eq5s
s2 ss; }`6-^lj
cout << "ss.c = " << &ss << endl ; ^k &zX!W
cout << "ss.d.a = " <<&ss.d.a << endl; I9*o[Jp5
cout << "ss.d.b = " <<&(ss.d.b) < cout << "ss.d = " <<&ss.e << endl; z:9
print out 各个变量的内存地址不就可以看出来了吗。 xou7j
l2GMVAca
所以答案是24,2. ASY
uZ
6CO>Tg:%
但是我的想像中应该是这样的分布情况: KIn^,d0H
c******* y$s}-O]/-
aa**bbbb L`FsK64@
dddddddd )<G>]IP<
jjBcoQU$o
不知为什么会c和a放在一起,组成8位长度。