Intel和微软同时出现的C语言面试题 ;l}- Z@! /
#pragma pack(8) 'EFyIVezg9
JMdPwI
struct s1{ h~wi6^{&Y
short a; 5{$LsL
long b; OxGE%R,
}; X>?b#Eva
n&A'C\
struct s2{ ^T~gEv
char c; q64k7<C,
s1 d; 16SOIT
long long e; /s];{m|>
}; >&!RWH9*q
X\}Y
#pragma pack() Bvt@X
~SvC[+t+U
问 5Zw1y@k(
1.sizeof(s2) = ? Y
wkyq>Rv
2.s2的s1中的a后面空了几个字节接着是b? p\{-t84n
bqQq=SO
OCy0#aPRS
BnRN;bu
如果您知道答案请在讨论中写出,以下是部份网友的答案,供参考: E\m5%bK\B
]59i>
网友rwxybh(行云)的答案: c]B$i*t
内存布局是 hm<}p&!J
1*** 11** N8`?t5
1111 **** Z0De!?ALV\
1111 1111 XlI!{qj|
R}mn*h6
所以答案就是24和3 8>/Q1(q0
#P#-xz
下面是一个测试的程序,试一试就知道了,我用的是VC2005 1
y}2+Kk
! Q<>3xZ
#pragma pack(8) 8.bKb<y
m?HZ;
struct s1{ P,=+W(s9}
short a; // 2 BYtes flgRpXt
long b; // 4 Bytes wM[~2C=vx
}; m*X[ Jtr
struct s2{ 'B0{U4?
char c; // 1 Byte Jgu94.;5
s1 d; // 8 Bytes -CH`>
long long e; // 8 Bytes {YUIMd!Y
}; [7m1Q<
// 1*** 11** ny-7P;->8
// 1111 **** (6v(9p
// 1111 1111 |#l=
// d*pF> j
aCV4AyG
// 00 01 02 03 04 05 06 07 L!_ZY
// 00 01 02 03 04 05 06 07 ;v
// 00 01 02 03 04 05 06 07 ;V<iL?
// DP/J(>eG
#pragma pack()
$hxNhI
>!6i3E^
int main(int argc, char* argv[]) /MQU
>&
{ VDB;%U*D
s2 a; T!W~n
ZC
char *p = (char *)&a; sS
TPMh
for(int i=0;i<24;++i) aAu>Tn86D.
p = (char)(i%8); -yDs<
Xl
printf("%d\n",sizeof(a)); ,7,g%?_P
printf("c=0x%lx\n",a.c); MzIq"3
printf("d.a=0x%x\n",a.d.a); e4OeoQ@ >
printf("d.b=0x%x\n",a.d.b); juBw5U<
printf("e=0x%llx\n",a.e); ;d$qc<2uA
return 0; VGL#!4wK
} x ]5@>5
结果: ]\RRqLDzkg
24 Y,8KPg@W
c=0x0 P\CDd=yWc
d.a=0x504 0tk#Gs[
d.b=0x3020100 VCy5JH
e=0x706050403020100 I &* _,d
gfU-"VpHE
&/.hx(#d
网友 redleaves (ID最吊的网友)的答案和分析: V E2tq k%
+MK6zf
如果代码: c^8o~K>w84
#pragma pack(8) +*oS((0s
struct S1{ >Q,zNs
char a; e7u^mJ
long b; -VDo[Zy
}; iAMtejw
struct S2 { 6{d6s#|%
char c; TaJB4zB
struct S1 d; 4(?G6y)
long long e; 1G~S|,8p
}; aKF*FFX
#pragma pack() b=a!j=-D
sizeof(S2)结果为24. ea=83 Zj
成员对齐有一个重要的条件,即每个成员分别对齐.即每个成员按自己的方式对齐. 'cDx{?
也就是说上面虽然指定了按8字节对齐,但并不是所有的成员都是以8字节对齐.其对齐的规则是,每个成员按其类型的对齐参数(通常是这个类型的大小)和指定对齐参数(这里是8字节)中较小的一个对齐.并且结构的长度必须为所用过的所有对齐参数的整数倍,不够就补空字节. cD1o"bq
&$`hQgi
S1中,成员a是1字节默认按1字节对齐,指定对齐参数为8,这两个值中取1,a按1字节对齐;成员b是4个字节,默认是按4字节对齐,这时就按4字节对齐,所以sizeof(S1)应该为8; {+zJI-XN/
S2中,c和S1中的a一样,按1字节对齐,而d 是个结构,它是8个字节,它按什么对齐呢?对于结构来说,它的默认对齐方式就是它的所有成员使用的对齐参数中最大的一个,S1的就是4.所以,成员d就是按4字节对齐.成员e是8个字节,它是默认按8字节对齐,和指定的一样,所以它对到8字节的边界上,这时,已经使用了12个字节了,所以又添加了4个字节的空,从第16个字节开始放置成员e.这时,长度为24,已经可以被8(成员e按8字节对齐)整除.这样,一共使用了24个字节. *5$&`&,
a b %[<Y9g,:Q
S1的内存布局:11**,1111, o-7>eE}+
c S1.a S1.b d !\[+99F#
S2的内存布局:1***,11**,1111,****11111111 ~`Qko-a&
M^rM-{?<
这里有三点很重要: _nT{g
1.每个成员分别按自己的方式对齐,并能最小化长度 3-40'$lE
2.复杂类型(如结构)的默认对齐方式是它最长的成员的对齐方式,这样在成员是复杂类型时,可以最小化长度 +w|9x.&W
3.对齐后的长度必须是成员中最大的对齐参数的整数倍,这样在处理数组时可以保证每一项都边界对齐 V's:>;
XC15 K@K
vjViX<#(V
网友xue23(xue23) 的答案和分析: puJ#w1!x`
!/K8xD$
有程序查一下各个变量的内存地址得知: 'k&?DZ!
各个变量在内存中的位置为 7dh1W@\
c***aa** ~$O1`IT
bbbb**** 'UM!*fk7C
dddddddd SN+S6
测试代码为: Jeqxspn
T
s2 ss; %>Xr5<$:&
cout << "ss.c = " << &ss << endl ; -jg (G GJ
cout << "ss.d.a = " <<&ss.d.a << endl; /7$mxtB5%L
cout << "ss.d.b = " <<&(ss.d.b) < cout << "ss.d = " <<&ss.e << endl; 47 u@4"M
print out 各个变量的内存地址不就可以看出来了吗。 E(<LvMiCa
+V v+K(lh$
所以答案是24,2. ZeasYSo4P
$7I]`Jt
但是我的想像中应该是这样的分布情况: B'>*[!A
c******* dw@E)
aa**bbbb ]8 U ~Iy
dddddddd .
,NB( s`
KiLvI,9y
不知为什么会c和a放在一起,组成8位长度。