Intel和微软同时出现的C语言面试题 fINM$ 6
#pragma pack(8) $Y,]D*|"K
$vy.BYFm
struct s1{ IFPywL{K
short a; ~ilbW|s?=k
long b; (p14{
}; FZA8@J|Q4
XpH[SRUx
struct s2{ de1&
char c; 2%W(^Lj
s1 d; s !8]CV>
long long e; nfDPM\FFD
}; CsSB'+&{
4kg9R^0
#pragma pack() jgbw'BBu
JpDYB
问 u>S&?X'a
1.sizeof(s2) = ? ]NAPvw#p
2.s2的s1中的a后面空了几个字节接着是b? GN1cnM>`
C
[2tH2*#
wOi>i`D&
5[gkGKkf_
如果您知道答案请在讨论中写出,以下是部份网友的答案,供参考: XY4s
$;;?'!%.
网友rwxybh(行云)的答案: *qb`wg
内存布局是 Op%^dwVG(v
1*** 11** u khI#:[
1111 **** 1C$^S]v%a
1111 1111 6xFZv
t
K.z}%a
所以答案就是24和3 e('c9 Y
"4tRy9q
下面是一个测试的程序,试一试就知道了,我用的是VC2005 *h =7:*n
x(b&r g.-0
#pragma pack(8) RPiCXpJv&
ao-C9|2>NU
struct s1{ 2%8N<GW.F
short a; // 2 BYtes bY>o%LL-
long b; // 4 Bytes 2s{yg%U(
}; I$mOy{/#
struct s2{ Ew:JpMR
char c; // 1 Byte XbH X,W$h
s1 d; // 8 Bytes _u:#2K$
long long e; // 8 Bytes <![T~<.
}; ZY/at/v
// 1*** 11** ,OasT!Sr
// 1111 **** sG VC+!E
// 1111 1111 MJg^
QVM
// f8&=D4)-w
ixS78KIr
// 00 01 02 03 04 05 06 07 D!mhR?t
// 00 01 02 03 04 05 06 07 4_"ZSVq]#
// 00 01 02 03 04 05 06 07 `\Npu
// |M
K-~ep
#pragma pack() 5%>U.X?i
_>`0!mG
int main(int argc, char* argv[]) X&lkA
(
{ ,!Hl@(
s2 a; #SqOJX~Q
char *p = (char *)&a; tRv#%>fj
for(int i=0;i<24;++i) XW#4C*5?d
p = (char)(i%8); Lw#hnLI.
printf("%d\n",sizeof(a)); J`mp8?;%
printf("c=0x%lx\n",a.c); .Nf*Yqs0
printf("d.a=0x%x\n",a.d.a); +'Ge?(E4_
printf("d.b=0x%x\n",a.d.b); p~mB;pZ%;
printf("e=0x%llx\n",a.e); 1_p'0lFe
return 0; [MEa@D<7N
} vv8$u3H
结果: $o @?D^
24 d)G-K+&B
c=0x0 qe$K6A %Yd
d.a=0x504 { &qBr&kg
d.b=0x3020100 bR6bS7$
e=0x706050403020100 f/c}XCH_h
,f1wN{P
eP2 y U
网友 redleaves (ID最吊的网友)的答案和分析: {Y@[hoHtF
>'T%=50YH
如果代码: ;I7Z*'5!
#pragma pack(8) GS,pl9#V_
struct S1{ ;4_n:XUgo;
char a; ~J2Q0Jv
long b; 9qW,I|G
}; X%-4x
struct S2 { WIGb7}egR
char c; t!=S[
struct S1 d; <7&b|f$CL
long long e; k@Tt,.];
}; "_l[4o[D
#pragma pack() 0PfFli`2;
sizeof(S2)结果为24. @<PL
成员对齐有一个重要的条件,即每个成员分别对齐.即每个成员按自己的方式对齐. 4Oy
c D
也就是说上面虽然指定了按8字节对齐,但并不是所有的成员都是以8字节对齐.其对齐的规则是,每个成员按其类型的对齐参数(通常是这个类型的大小)和指定对齐参数(这里是8字节)中较小的一个对齐.并且结构的长度必须为所用过的所有对齐参数的整数倍,不够就补空字节. _YJw F1e+M
vLke,MKW
S1中,成员a是1字节默认按1字节对齐,指定对齐参数为8,这两个值中取1,a按1字节对齐;成员b是4个字节,默认是按4字节对齐,这时就按4字节对齐,所以sizeof(S1)应该为8; fU}w81oe
S2中,c和S1中的a一样,按1字节对齐,而d 是个结构,它是8个字节,它按什么对齐呢?对于结构来说,它的默认对齐方式就是它的所有成员使用的对齐参数中最大的一个,S1的就是4.所以,成员d就是按4字节对齐.成员e是8个字节,它是默认按8字节对齐,和指定的一样,所以它对到8字节的边界上,这时,已经使用了12个字节了,所以又添加了4个字节的空,从第16个字节开始放置成员e.这时,长度为24,已经可以被8(成员e按8字节对齐)整除.这样,一共使用了24个字节. i!HGM=f
a b Lf-8G5G
S1的内存布局:11**,1111, ~9c9@!RA2
c S1.a S1.b d aj,ZM,Ad
S2的内存布局:1***,11**,1111,****11111111 'I~dJEW7
MQ+ek4
这里有三点很重要: 5R Hs
1.每个成员分别按自己的方式对齐,并能最小化长度 }Q=Zqlvz
2.复杂类型(如结构)的默认对齐方式是它最长的成员的对齐方式,这样在成员是复杂类型时,可以最小化长度 _SaK]7}m!
3.对齐后的长度必须是成员中最大的对齐参数的整数倍,这样在处理数组时可以保证每一项都边界对齐 a9I8WQ
meL'toaJdQ
"+WR[-n>\
网友xue23(xue23) 的答案和分析: /7#&qx8
^
UzF
nW@a
有程序查一下各个变量的内存地址得知: 8tL61x{]
各个变量在内存中的位置为 L8G4K)
c***aa** 4{?x(~
bbbb**** tWiV0PTI
dddddddd bDo'hDmW
测试代码为: _"bx#B*
s2 ss; d5\1-d_uz
cout << "ss.c = " << &ss << endl ; op*+fJHD
cout << "ss.d.a = " <<&ss.d.a << endl; }';&0p2Z
cout << "ss.d.b = " <<&(ss.d.b) < cout << "ss.d = " <<&ss.e << endl; kT1lOP-Bg
print out 各个变量的内存地址不就可以看出来了吗。 VJ"3G;;
~<%cc+;`
所以答案是24,2. U)!AH^{32
yU.0'r5uR
但是我的想像中应该是这样的分布情况: F"=MU8
c******* ,54<U~Lg:
aa**bbbb Wg%-m%7O
dddddddd t>fB@xHBB
8zCAy@u
不知为什么会c和a放在一起,组成8位长度。