Intel和微软同时出现的C语言面试题 fMjn8.
#pragma pack(8) h:QKd!Gq
M[5zn
struct s1{ 76[O3%
short a; ?#@JH
long b; 5.J$0wK'6
}; Xrnxpp!#^D
@;>TmLs
struct s2{ :[gM 5G
char c; sY?pp
'}a
s1 d; &(!Sy?tNe
long long e; jEBZ"Jvb
}; L]{ 1"`#
ybBLBJb
#pragma pack() ^FSUK
K~nk:}3Ui
问 [3`T/Wm
1.sizeof(s2) = ? 5m")GWQaP@
2.s2的s1中的a后面空了几个字节接着是b? 7+aTrE{
Y$3H$F.+
#84pRU~
zGFo-C
如果您知道答案请在讨论中写出,以下是部份网友的答案,供参考: ?' H);ou-p
oD,f5Ci-
网友rwxybh(行云)的答案:
v#/Uq?us
内存布局是 Ij>x3L\-
1*** 11** Y7R"~IA$
1111 **** 8ID
fYJ
1111 1111 \nV|Y=5
eWO^n>Y
所以答案就是24和3 u/FnA-L4
7*5$=z4,1
下面是一个测试的程序,试一试就知道了,我用的是VC2005 C)>
])'S
w5"C<5^
#pragma pack(8) }S6Sz&)
IC}?oXs5G
struct s1{ _H|c_
short a; // 2 BYtes S5ka;g
long b; // 4 Bytes Oqzz9+
}; $3](6
struct s2{ {HeIY2
char c; // 1 Byte &F"Mkyf
s1 d; // 8 Bytes <Gzy*1Q&
long long e; // 8 Bytes *&)<'6
}; >`DbT:/<
// 1*** 11** _xign 3
// 1111 **** iK%<0m
// 1111 1111 07-S%L7Z
// pYV$sDlD
BDY@&vF
// 00 01 02 03 04 05 06 07 '01H8er
// 00 01 02 03 04 05 06 07 Ak%M,``(L
// 00 01 02 03 04 05 06 07 ,-Fhb~u
// T{u!4Yu
#pragma pack() DsY-JBDvoz
D"fE )@Q@Y
int main(int argc, char* argv[]) 5,>1rd<B
{ We3*WsX\
s2 a; N m-{$U
char *p = (char *)&a; yG58?5\9
for(int i=0;i<24;++i) +]Of f^s
p = (char)(i%8); W?{:HV
printf("%d\n",sizeof(a)); W5?F?Dp!v
printf("c=0x%lx\n",a.c); N!DAn\g
printf("d.a=0x%x\n",a.d.a); V#!ihL/>
printf("d.b=0x%x\n",a.d.b); qOz,iR?}
printf("e=0x%llx\n",a.e); p8y_uNQE
return 0; $DW3H1iW
} F.?`<7
结果: E!'H,#"P
24 94r8DkI
c=0x0 !o &+
d.a=0x504 *!UY;InanX
d.b=0x3020100 _GK^ 7}u
e=0x706050403020100 Y-&r_s_~
{s|rk
dz.]5R
网友 redleaves (ID最吊的网友)的答案和分析: eN{[T
PPCq
xEaRuH c
如果代码: u3kK!2cdP
#pragma pack(8) UiS9uGj
struct S1{ %JDG aG'
char a; \Q{@AC<?i
long b; hu\HK81m
}; 5bFE;Y;
struct S2 { H V<|eL #
char c; "s2?cQv{#
struct S1 d; NAhV8
long long e; +O3zeL
}; c;e-[F 7
#pragma pack() "5e~19
sizeof(S2)结果为24. @Fqh]1t
成员对齐有一个重要的条件,即每个成员分别对齐.即每个成员按自己的方式对齐. ]CH@T9d5V
也就是说上面虽然指定了按8字节对齐,但并不是所有的成员都是以8字节对齐.其对齐的规则是,每个成员按其类型的对齐参数(通常是这个类型的大小)和指定对齐参数(这里是8字节)中较小的一个对齐.并且结构的长度必须为所用过的所有对齐参数的整数倍,不够就补空字节. I#@iA!
1Nw&Z0MI
S1中,成员a是1字节默认按1字节对齐,指定对齐参数为8,这两个值中取1,a按1字节对齐;成员b是4个字节,默认是按4字节对齐,这时就按4字节对齐,所以sizeof(S1)应该为8; 4cL
NPl<
S2中,c和S1中的a一样,按1字节对齐,而d 是个结构,它是8个字节,它按什么对齐呢?对于结构来说,它的默认对齐方式就是它的所有成员使用的对齐参数中最大的一个,S1的就是4.所以,成员d就是按4字节对齐.成员e是8个字节,它是默认按8字节对齐,和指定的一样,所以它对到8字节的边界上,这时,已经使用了12个字节了,所以又添加了4个字节的空,从第16个字节开始放置成员e.这时,长度为24,已经可以被8(成员e按8字节对齐)整除.这样,一共使用了24个字节. )H$Ik)/N
a b XEV-D9n
S1的内存布局:11**,1111, B?-RzWB\3
c S1.a S1.b d }uWJ
S2的内存布局:1***,11**,1111,****11111111 $G5m/[KDI
G;V@oT
这里有三点很重要: ,T"pUe VJ
1.每个成员分别按自己的方式对齐,并能最小化长度 JU:!lyd
2.复杂类型(如结构)的默认对齐方式是它最长的成员的对齐方式,这样在成员是复杂类型时,可以最小化长度 NKLGbH
3.对齐后的长度必须是成员中最大的对齐参数的整数倍,这样在处理数组时可以保证每一项都边界对齐 F1R91V|
"e g`3v
:ORCsl6-
网友xue23(xue23) 的答案和分析: 7CUu:6%
@8Drhx
有程序查一下各个变量的内存地址得知: UT [7 J
各个变量在内存中的位置为 0m)["g4
c***aa** >1a-}>r
bbbb**** u#%Ig3
dddddddd .=rv,PWjZ
测试代码为: [e3|yE6
s2 ss; 2ko7t9y&
cout << "ss.c = " << &ss << endl ; +%X_+9bd
cout << "ss.d.a = " <<&ss.d.a << endl; k@5#^G
cout << "ss.d.b = " <<&(ss.d.b) < cout << "ss.d = " <<&ss.e << endl; KpC)A5u6
print out 各个变量的内存地址不就可以看出来了吗。 PqPLy
B P"PUl:
所以答案是24,2. jM1_+Lm1
\l{*1lQ`
但是我的想像中应该是这样的分布情况: MTb}um.($
c******* = Ii@-C
aa**bbbb f1=BBQY
>
dddddddd J[YA1
R%aH{UhE`
不知为什么会c和a放在一起,组成8位长度。