Intel和微软同时出现的C语言面试题 K~{$oD7!
#pragma pack(8) NjScc%@y
QB uMJm
struct s1{ Ad8n<zt|
short a; ;>yxNGV`
long b; ]EBxl=C}D
}; YMcD|Kb p
u#$]?($}d
struct s2{ Y|f[bw
char c; <tNBxa$gS
s1 d; Qf+\;@
long long e; y/cvQY0pU
}; c
/HHy,
?k&Vy
#pragma pack() L:j<c5
_x'6]f{n
问 ^z IW+:
1.sizeof(s2) = ? F=e8 IUr
2.s2的s1中的a后面空了几个字节接着是b? \BTODZ:h
zuad~%D<I
85:=4N%
XbKYiy
如果您知道答案请在讨论中写出,以下是部份网友的答案,供参考: 9igiZmM
4y?n
[/M/
网友rwxybh(行云)的答案: u(>^3PJ+
内存布局是 M*, -zGr
1*** 11** !qh]6%l
1111 **** ,{u
yG:
1111 1111 '(f* 2eE:
Uw. `7b>B
所以答案就是24和3 wPd3F.<$
QUc= &5 %
下面是一个测试的程序,试一试就知道了,我用的是VC2005 ^R7lom.
rdP[<Y9
#pragma pack(8) 4{U T!WIi
gjwn7_
struct s1{ ^e _hLX\SW
short a; // 2 BYtes x7&B$.>3
long b; // 4 Bytes @s;;O\
}; H?vdr:WlTN
struct s2{ IqaT?+O\?r
char c; // 1 Byte 3*"WG O5
s1 d; // 8 Bytes XK3tgaH
long long e; // 8 Bytes XkE`U5.
}; Bi 3<7
// 1*** 11** rNWw?_H-H(
// 1111 **** $oID(P
// 1111 1111 *xxx:*6rk;
// KE5kOU;
1~Y<//5E
// 00 01 02 03 04 05 06 07 qpP=K $
// 00 01 02 03 04 05 06 07 ooj,/IEQ
// 00 01 02 03 04 05 06 07
!Y0Vid
// @]%IK(|
#pragma pack() i(%W_d!
2^[`e g
int main(int argc, char* argv[]) TOB-aAO
{ I(L,8n5
s2 a; |^"1{7)
char *p = (char *)&a; )Xz,j9GzJS
for(int i=0;i<24;++i) eCU:Q
p = (char)(i%8); "Y
=;.:qe
printf("%d\n",sizeof(a)); .PIL
+x*]N
printf("c=0x%lx\n",a.c); TCwFPlF|
printf("d.a=0x%x\n",a.d.a); o4F2%0gJ
printf("d.b=0x%x\n",a.d.b); s^G.]%iU
printf("e=0x%llx\n",a.e); 3=P]x;[ba
return 0; 6
6EV$*dRL
} NqazpB*
结果: w7.V6S$Ga
24 +K:Dx!9
c=0x0 bQg:zww
d.a=0x504 Ha0M)0Anv
d.b=0x3020100 p J!
mw\:
e=0x706050403020100 /!yU!`bY
h,u,^ r
%op**@4/t\
网友 redleaves (ID最吊的网友)的答案和分析: B[Ku\A6&
)1J R#
如果代码: n`B:;2X,
#pragma pack(8) Ct <udO
struct S1{ _/s$ZCd
char a; *MhRW,=
long b; p?%y82E
}; c \J:![x
struct S2 { ul6]!Iy
char c; qdJ=lhHM}
struct S1 d; 36&e.3/#
long long e; F4-$~v@
}; K*vt;L
#pragma pack() w>s,"2&5J
sizeof(S2)结果为24. .GPT!lDc
成员对齐有一个重要的条件,即每个成员分别对齐.即每个成员按自己的方式对齐. YNyk1cE
也就是说上面虽然指定了按8字节对齐,但并不是所有的成员都是以8字节对齐.其对齐的规则是,每个成员按其类型的对齐参数(通常是这个类型的大小)和指定对齐参数(这里是8字节)中较小的一个对齐.并且结构的长度必须为所用过的所有对齐参数的整数倍,不够就补空字节. hP%M?MKC
*MFIV02[N
S1中,成员a是1字节默认按1字节对齐,指定对齐参数为8,这两个值中取1,a按1字节对齐;成员b是4个字节,默认是按4字节对齐,这时就按4字节对齐,所以sizeof(S1)应该为8; MC&` oX[
S2中,c和S1中的a一样,按1字节对齐,而d 是个结构,它是8个字节,它按什么对齐呢?对于结构来说,它的默认对齐方式就是它的所有成员使用的对齐参数中最大的一个,S1的就是4.所以,成员d就是按4字节对齐.成员e是8个字节,它是默认按8字节对齐,和指定的一样,所以它对到8字节的边界上,这时,已经使用了12个字节了,所以又添加了4个字节的空,从第16个字节开始放置成员e.这时,长度为24,已经可以被8(成员e按8字节对齐)整除.这样,一共使用了24个字节. Tj`,Z5vy
a b 5K1)1E/Fu
S1的内存布局:11**,1111, bivuqKA
c S1.a S1.b d ntX3Nt_n
S2的内存布局:1***,11**,1111,****11111111 :\`o8`
}#RakV4
这里有三点很重要: ,GhS[VJjR
1.每个成员分别按自己的方式对齐,并能最小化长度 Hh3X
\
2.复杂类型(如结构)的默认对齐方式是它最长的成员的对齐方式,这样在成员是复杂类型时,可以最小化长度 iJI }TVep#
3.对齐后的长度必须是成员中最大的对齐参数的整数倍,这样在处理数组时可以保证每一项都边界对齐 I3{PZhU.
CAig]=2'
:S{BbQ){]
网友xue23(xue23) 的答案和分析: \j}ZB<.>
R6<X%*&%
有程序查一下各个变量的内存地址得知: \_VA50
各个变量在内存中的位置为 hohfE3rd
c***aa** $lfn(b,
bbbb**** $ZhFh{DQ.
dddddddd b4%??"&<Y
测试代码为: g-4M3of
s2 ss; w_"E*9
cout << "ss.c = " << &ss << endl ; ONB{_X?
cout << "ss.d.a = " <<&ss.d.a << endl; }1L4"}L.
cout << "ss.d.b = " <<&(ss.d.b) < cout << "ss.d = " <<&ss.e << endl; )Yh+c=6
?
print out 各个变量的内存地址不就可以看出来了吗。 38Mv25N
MIeU,KT#U
所以答案是24,2. a_^\=&?'
/Vx7mF:
但是我的想像中应该是这样的分布情况: ]Grek<
c******* :".ARCg
aa**bbbb ]`!>6/[
dddddddd ,a{P4Bq
o=:9y-nH
不知为什么会c和a放在一起,组成8位长度。