Intel和微软同时出现的C语言面试题 (n":]8}
#pragma pack(8) h}anTFKP
_V_8p)%
struct s1{ a'_MhJ zs
short a; \p>]G[g
long b; Y^c,mK^
}; X] JpS
`mq4WXO\
struct s2{ _e:5XQ
char c; 0p:ClM2O
s1 d; ;+r) j"W
long long e; bMqu5G_q
}; 1^x2WlUm4
6mI_Q2
#pragma pack() wZ]BY;
O]Ry3j
问 5O;a/q8"
1.sizeof(s2) = ? 9%3 r-U=
2.s2的s1中的a后面空了几个字节接着是b? dPH!
V6r
s{"`=dKT
I |<+'G
9z|>roNe
如果您知道答案请在讨论中写出,以下是部份网友的答案,供参考: N#pl mPrZ
PxP?hk
网友rwxybh(行云)的答案: rx}ujjx
内存布局是 /+<%,c$n
1*** 11** c5B_WqjJ
1111 **** gq/ePSa
1111 1111 ,IT)zCpaBP
+c]N]?k&
所以答案就是24和3 U<gUX07
z~}StCH(
下面是一个测试的程序,试一试就知道了,我用的是VC2005 7+D'W7Yx
9h3~;Q
#pragma pack(8) Cdt,//xrz
GqIvvnw@f
struct s1{ aV?}+Y{#
short a; // 2 BYtes skR,M=F~
long b; // 4 Bytes j?f,~Y<k
}; g6@N PQ
struct s2{ ~/|unV
char c; // 1 Byte +]S;U&vQ
s1 d; // 8 Bytes H4y1Hpa,
long long e; // 8 Bytes r.a9W?(E
}; o%4&1^ Vg
// 1*** 11** m m J)m
// 1111 **** <D;H}ef
// 1111 1111
_A)_K;cz
// TN |{P
l|ZzG4]+l
// 00 01 02 03 04 05 06 07 NqQ(X'W7
// 00 01 02 03 04 05 06 07 Hz3 S^o7
// 00 01 02 03 04 05 06 07 $@u^Jt, ?
// 1VjeP
*
#pragma pack() /SqFP
L]
-9H!j4]T?
int main(int argc, char* argv[]) DX%8.@
{ 3Q*RR"3
s2 a; uZ0 $s$
char *p = (char *)&a; S\v&{
for(int i=0;i<24;++i) St3(1mApl
p = (char)(i%8); WkDn
printf("%d\n",sizeof(a)); tRUsZl
printf("c=0x%lx\n",a.c); 6t7;}t]t
printf("d.a=0x%x\n",a.d.a); >+;
b>
printf("d.b=0x%x\n",a.d.b); pZ_FVID
printf("e=0x%llx\n",a.e); (!>g8=`"
return 0; !aW*dD61
} %8}ksl07
结果: Z z;<P
24 {Jw<<<G
c=0x0 W
&0@&U
d.a=0x504 Z'>eT)
d.b=0x3020100 G%p!os\>
e=0x706050403020100 :WfB!4%!
UB&S 2g
ZTBFV/{
网友 redleaves (ID最吊的网友)的答案和分析: WW\)B-}T
O 44IH`SI
如果代码: e}Af"LI
#pragma pack(8) zy/tQGTr@
struct S1{ |{/O)3
char a; wh7a|
long b; ^pQ;0[9Y0
}; vn%U;}
struct S2 { %\{?(baOA
char c; Eps\iykB
struct S1 d; (y+5d00
long long e; li_pM!dWU_
}; [>J~M!yu:r
#pragma pack() [-Dgo1}Qr
sizeof(S2)结果为24. eVCkPv*
成员对齐有一个重要的条件,即每个成员分别对齐.即每个成员按自己的方式对齐. 0p>:rU~
也就是说上面虽然指定了按8字节对齐,但并不是所有的成员都是以8字节对齐.其对齐的规则是,每个成员按其类型的对齐参数(通常是这个类型的大小)和指定对齐参数(这里是8字节)中较小的一个对齐.并且结构的长度必须为所用过的所有对齐参数的整数倍,不够就补空字节. 6B;_uIq5
FvI0 J
S1中,成员a是1字节默认按1字节对齐,指定对齐参数为8,这两个值中取1,a按1字节对齐;成员b是4个字节,默认是按4字节对齐,这时就按4字节对齐,所以sizeof(S1)应该为8; dVmAMQk.g
S2中,c和S1中的a一样,按1字节对齐,而d 是个结构,它是8个字节,它按什么对齐呢?对于结构来说,它的默认对齐方式就是它的所有成员使用的对齐参数中最大的一个,S1的就是4.所以,成员d就是按4字节对齐.成员e是8个字节,它是默认按8字节对齐,和指定的一样,所以它对到8字节的边界上,这时,已经使用了12个字节了,所以又添加了4个字节的空,从第16个字节开始放置成员e.这时,长度为24,已经可以被8(成员e按8字节对齐)整除.这样,一共使用了24个字节. <1g 1hqK3
a b E-U;8cOMv
S1的内存布局:11**,1111, | 7'yk__m
c S1.a S1.b d ]g-qWSKU
S2的内存布局:1***,11**,1111,****11111111 J|2Hqd
c7nk~K[6
这里有三点很重要: +} ! F(c
1.每个成员分别按自己的方式对齐,并能最小化长度 }rMpp[
2.复杂类型(如结构)的默认对齐方式是它最长的成员的对齐方式,这样在成员是复杂类型时,可以最小化长度 G4exk5
3.对齐后的长度必须是成员中最大的对齐参数的整数倍,这样在处理数组时可以保证每一项都边界对齐 Znl>*e/|
XFf+efh
iJaNP%N
网友xue23(xue23) 的答案和分析: lRATrp#T
^SSOh#
有程序查一下各个变量的内存地址得知: CTbhwY(/
各个变量在内存中的位置为 @#--dOWYR
c***aa** agxSb^ 8tF
bbbb**** hzPB~obC
dddddddd
jQ\
MB
测试代码为: #<i><EG
s2 ss; .McoW7|Y
cout << "ss.c = " << &ss << endl ; Lc: SqF
cout << "ss.d.a = " <<&ss.d.a << endl; p:Ld)U *
cout << "ss.d.b = " <<&(ss.d.b) < cout << "ss.d = " <<&ss.e << endl; vzrD"
print out 各个变量的内存地址不就可以看出来了吗。 q(ET)xCeD
sv{0XVn+^
所以答案是24,2. ^Lv^W
%J (
}D7-,
但是我的想像中应该是这样的分布情况: yE|}
r
c******* z.9FDQLp
aa**bbbb l[\,*C
dddddddd +uiH0iGS
%:;[M|.
不知为什么会c和a放在一起,组成8位长度。