Intel和微软同时出现的C语言面试题 kL,AY-Iu{@
#pragma pack(8) Hc4]2pf
Yt7R[|
struct s1{ a!P?RbW
short a; N/mTG2'<
long b; zD-.bHo>.
}; 50Co/-)j
=g$%.
struct s2{ 9#.nNv*z3
char c; 6<R!`N 6
s1 d; -}{c;pT
long long e; >ZuWsA0q
}; e&E""ye
n_hV;
#pragma pack() &aaXw?/zr
](@Tbm8
问 -D0kp~AO4N
1.sizeof(s2) = ? *<zfe.
2.s2的s1中的a后面空了几个字节接着是b? Sim\+SL{#
zVYX#- nv
sC48o'8(
Edc< 8-
如果您知道答案请在讨论中写出,以下是部份网友的答案,供参考: }i./,
frk(2C8T
网友rwxybh(行云)的答案: $+)SW{7
内存布局是 [F/>pL5U$
1*** 11** gEMxK2MNXj
1111 **** {?17Zth
1111 1111 B3]q*ERAo
NB;8 e>8
所以答案就是24和3 noC]&4b
E=3<F_3W
下面是一个测试的程序,试一试就知道了,我用的是VC2005 YUat}-S
ne4hR]:
#pragma pack(8) ]i)m
,n}X,#]
struct s1{ 5vxJ|Hse@
short a; // 2 BYtes &[}bHX/
long b; // 4 Bytes =U!M,zw4
}; 0$%:zHi5g
struct s2{ dQQh$*IL?{
char c; // 1 Byte (2Z-NVU#
s1 d; // 8 Bytes { ,qm=Xjq
long long e; // 8 Bytes n:,At]ky
}; R~iJ5@[
// 1*** 11** (\>3FwFHW|
// 1111 **** (V)nHF*<>
// 1111 1111 Jc"xH~,
// N2vSJ\u
kqYWa`eE
// 00 01 02 03 04 05 06 07 \L-o>O
// 00 01 02 03 04 05 06 07 eYMp@Cx
// 00 01 02 03 04 05 06 07 /\V-1 7-
// (PE x<r1
#pragma pack() $+!/=8R)
SZW`|ajH
int main(int argc, char* argv[]) B>WAlmPA
{ +1~Y2
s2 a; 9`81br+~
char *p = (char *)&a; R$IxR=hMx
for(int i=0;i<24;++i) '.r_6X$7Jt
p = (char)(i%8); Q\z6/1:9Z
printf("%d\n",sizeof(a)); fwK5p?Xhm
printf("c=0x%lx\n",a.c); t23uQR#>b_
printf("d.a=0x%x\n",a.d.a); D |kdk;Xv
printf("d.b=0x%x\n",a.d.b); `+[Ct08
printf("e=0x%llx\n",a.e); Z1
%"w*U
return 0; gE]6]L
} D]\of#%T
结果: $8vZiB!"
24 ZgK[,<2
c=0x0 Kur3Gf X
d.a=0x504 ]KdSwIbi
d.b=0x3020100 7)tkqfb]
e=0x706050403020100 ~v"4;A6
@&p:J0hbp
uT:'Kkb!
网友 redleaves (ID最吊的网友)的答案和分析: :jlKj} 4A
,$s
NfW
如果代码: M?l/_!QB
#pragma pack(8) z{Z4{&M
struct S1{ \ :To\6\Ri
char a; jR[VPm=
long b; lZ|+.T!g?
}; lKWe=xY\B
struct S2 { u0 myB/`
char c; (Ild>_Tdb`
struct S1 d; 2CcUClP$
long long e; f]%:.N~1w
}; =jXBF.
#pragma pack() #@FMH*?xX6
sizeof(S2)结果为24. m:&go2Y
成员对齐有一个重要的条件,即每个成员分别对齐.即每个成员按自己的方式对齐. =?]H`T:
也就是说上面虽然指定了按8字节对齐,但并不是所有的成员都是以8字节对齐.其对齐的规则是,每个成员按其类型的对齐参数(通常是这个类型的大小)和指定对齐参数(这里是8字节)中较小的一个对齐.并且结构的长度必须为所用过的所有对齐参数的整数倍,不够就补空字节. BdBwfH%:
@yp#k>
S1中,成员a是1字节默认按1字节对齐,指定对齐参数为8,这两个值中取1,a按1字节对齐;成员b是4个字节,默认是按4字节对齐,这时就按4字节对齐,所以sizeof(S1)应该为8; Cw6\'p%l-\
S2中,c和S1中的a一样,按1字节对齐,而d 是个结构,它是8个字节,它按什么对齐呢?对于结构来说,它的默认对齐方式就是它的所有成员使用的对齐参数中最大的一个,S1的就是4.所以,成员d就是按4字节对齐.成员e是8个字节,它是默认按8字节对齐,和指定的一样,所以它对到8字节的边界上,这时,已经使用了12个字节了,所以又添加了4个字节的空,从第16个字节开始放置成员e.这时,长度为24,已经可以被8(成员e按8字节对齐)整除.这样,一共使用了24个字节. 0M=A,`qk
a b (iQ<
[3C=
S1的内存布局:11**,1111, 0z&]imU
c S1.a S1.b d E><$sN6
S2的内存布局:1***,11**,1111,****11111111 .aS`l~6
3/_rbPr
这里有三点很重要: pGz 5!d
1.每个成员分别按自己的方式对齐,并能最小化长度 C.qNBl*
2.复杂类型(如结构)的默认对齐方式是它最长的成员的对齐方式,这样在成员是复杂类型时,可以最小化长度 'D_a2xo0
3.对齐后的长度必须是成员中最大的对齐参数的整数倍,这样在处理数组时可以保证每一项都边界对齐 =rz7 x
IAyyRl\
#&0G$~
网友xue23(xue23) 的答案和分析: 4Z8FLA+T,
<O:}dXqZ
有程序查一下各个变量的内存地址得知: : EA-L
各个变量在内存中的位置为 {txW>rZX
c***aa** @^P<(%p
bbbb**** XhEZTg;
dddddddd )
uM*`%
测试代码为: /LwS|c6}}
s2 ss; O-P'Ff"}t
cout << "ss.c = " << &ss << endl ; XZ%3PMq
cout << "ss.d.a = " <<&ss.d.a << endl; uuHg=8(
cout << "ss.d.b = " <<&(ss.d.b) < cout << "ss.d = " <<&ss.e << endl; <pA%|]
print out 各个变量的内存地址不就可以看出来了吗。 0zQ~'x
co^bS;r
所以答案是24,2. YV%y
KD
p^.qwP\P
但是我的想像中应该是这样的分布情况: we:P_\6
c******* L%S(z)xX3
aa**bbbb -g n!8G1
dddddddd 2P35#QI[)
|L9p. q
不知为什么会c和a放在一起,组成8位长度。