Intel和微软同时出现的C语言面试题 g\?7M1~
#pragma pack(8) p-%m/d?
kc"SUiy/
struct s1{ F[oTc^dr
short a; g
_u
long b; =Wl}Pgo!
}; H|B4.z
&qeMYYY
struct s2{ H?'t>JX
char c; ^@xn 3zJ
s1 d; q6N6QI8/
long long e; 4kf8Am(
}; !\1Pu|
gA DF
#pragma pack() ^$F1U,oi
Z|$OPMLX
问 4VfZw\^
1.sizeof(s2) = ? t>(}LV.
2.s2的s1中的a后面空了几个字节接着是b? >[gNQJ6
;*8,PV0b_<
SH M@H93
g%f6D%d)A
如果您知道答案请在讨论中写出,以下是部份网友的答案,供参考: %$SO9PY
'"Y(2grP
网友rwxybh(行云)的答案: %w3"B,k'9D
内存布局是 +yo1&b R/
1*** 11** ?mJ&zf|B8
1111 **** !qF t:{-h
1111 1111 jz72~+)T
L9":=
所以答案就是24和3
tEHgQto
rWB/#m
下面是一个测试的程序,试一试就知道了,我用的是VC2005 i-*ZW:
79O'S du@
#pragma pack(8) Doc_rQYku
&pZncm
struct s1{ $c<NEt_\
short a; // 2 BYtes L:E?tR}H
long b; // 4 Bytes QNesiV0MI
}; G2BB]] m3
struct s2{ ==)q{e5
char c; // 1 Byte $|%BaEyk
s1 d; // 8 Bytes W 2.Ap
long long e; // 8 Bytes :M
_N
}; }*9mNE
// 1*** 11** 's_[#a;Vp
// 1111 **** kx31g,cf]w
// 1111 1111 Vx*O^cM
// 5Gw B1}q
%29lDd(<
// 00 01 02 03 04 05 06 07 YwnYTt
// 00 01 02 03 04 05 06 07 H4"'&A7$
// 00 01 02 03 04 05 06 07 c$#7Kp4
// {~cM 6W]f
#pragma pack() JsD|igqF-
Q.Xs%{B
int main(int argc, char* argv[]) G3_HX<|f*
{ ,A9_xdv5
s2 a; *9O@DF&*6
char *p = (char *)&a; xka&,`z
for(int i=0;i<24;++i) ^e\H V4s
p = (char)(i%8); {DWL 5V#M
printf("%d\n",sizeof(a)); Bx9v2x.
printf("c=0x%lx\n",a.c); s_}q
printf("d.a=0x%x\n",a.d.a); Jy?; <
printf("d.b=0x%x\n",a.d.b); s@D/.X
printf("e=0x%llx\n",a.e); *r(Qy0(
return 0; ve f9*u`
} !j%MN{#a
结果: DrA\-G_7
24 |e{ ^Yf4
c=0x0 k$3Iv"gbx
d.a=0x504 c$^~7.~{Qy
d.b=0x3020100 eY\w?pT2
e=0x706050403020100 x@#aOf4<U
r&3EM[*Iw
yIYQ.-DkS+
网友 redleaves (ID最吊的网友)的答案和分析: Nbb2wr9A
Kw=][}d`D
如果代码: ,s`4k?y
#pragma pack(8) pc2;2^U_
struct S1{ vR4omB{
char a; l/-qVAd!q
long b; sT'j36Nc<,
}; bJoP@s
struct S2 { crQ_@@X?<
char c; :hTmt{LjN
struct S1 d;
Ruv`yfQ
long long e; }'`}| pM$
}; {PKf]m
#pragma pack() L<k(stx~
sizeof(S2)结果为24. Y_nl9}&+C0
成员对齐有一个重要的条件,即每个成员分别对齐.即每个成员按自己的方式对齐. 4^T_" W}
也就是说上面虽然指定了按8字节对齐,但并不是所有的成员都是以8字节对齐.其对齐的规则是,每个成员按其类型的对齐参数(通常是这个类型的大小)和指定对齐参数(这里是8字节)中较小的一个对齐.并且结构的长度必须为所用过的所有对齐参数的整数倍,不够就补空字节. tUi@'%>=5
S S fNI>
S1中,成员a是1字节默认按1字节对齐,指定对齐参数为8,这两个值中取1,a按1字节对齐;成员b是4个字节,默认是按4字节对齐,这时就按4字节对齐,所以sizeof(S1)应该为8; TeRH@oI
S2中,c和S1中的a一样,按1字节对齐,而d 是个结构,它是8个字节,它按什么对齐呢?对于结构来说,它的默认对齐方式就是它的所有成员使用的对齐参数中最大的一个,S1的就是4.所以,成员d就是按4字节对齐.成员e是8个字节,它是默认按8字节对齐,和指定的一样,所以它对到8字节的边界上,这时,已经使用了12个字节了,所以又添加了4个字节的空,从第16个字节开始放置成员e.这时,长度为24,已经可以被8(成员e按8字节对齐)整除.这样,一共使用了24个字节. \+j:d9?
a b UM2yv6:/
S1的内存布局:11**,1111, ]Z?jo#F
c S1.a S1.b d 4JRQ=T|P7I
S2的内存布局:1***,11**,1111,****11111111 B ?l0u
[ J4n%
这里有三点很重要: c 5 `74g
1.每个成员分别按自己的方式对齐,并能最小化长度 XhUVDmeUMb
2.复杂类型(如结构)的默认对齐方式是它最长的成员的对齐方式,这样在成员是复杂类型时,可以最小化长度 %7[q%S
3.对齐后的长度必须是成员中最大的对齐参数的整数倍,这样在处理数组时可以保证每一项都边界对齐 p
z\8Bp}yo
{r%T_BfY
&H[7UyC
网友xue23(xue23) 的答案和分析: ?[;>1+D
QmMA]Q
有程序查一下各个变量的内存地址得知: &"(zK"O
各个变量在内存中的位置为 1zgM$p
c***aa** kB.CeG]tk
bbbb**** YJ|U|[
dddddddd '61>.u:2
测试代码为: *7w!~mn[m
s2 ss; ~G1B}c]
cout << "ss.c = " << &ss << endl ; wg<t*6&'x
cout << "ss.d.a = " <<&ss.d.a << endl; zkquXzlgB
cout << "ss.d.b = " <<&(ss.d.b) < cout << "ss.d = " <<&ss.e << endl; N:;z~`
print out 各个变量的内存地址不就可以看出来了吗。 dQ_hlx!J
Rg^ps
所以答案是24,2. 1@i/N
Xck`"RU<xA
但是我的想像中应该是这样的分布情况: gJ~CD1`O
c******* Z/T(4
aa**bbbb V"B/4v>
dddddddd C-\3,
T;]Ob3(BpW
不知为什么会c和a放在一起,组成8位长度。