Intel和微软同时出现的C语言面试题 W6wgX0H
#pragma pack(8) #]:nQ(
?[VS0IBS
struct s1{ FQ O6w'
short a; %Xp}d5-
long b; \UK 9
}; \/lS!+~'']
e#16,a-}o
struct s2{ 'f5,%e2#
char c; }hl#
e[$
s1 d; fv`%w
long long e; rGq~e|.O3
}; &WsDYov?
vsES`
#pragma pack() h^[K= J
1Rwk}wL
问 8HTV"60hTs
1.sizeof(s2) = ? *[_?4*F
2.s2的s1中的a后面空了几个字节接着是b? T_I"Tsv
zFv>'1$
^WM)UZEBC
)!M:=}."
如果您知道答案请在讨论中写出,以下是部份网友的答案,供参考: #PtV=Ee1
+]*?J1Y8Z
网友rwxybh(行云)的答案: wRU pQ~=B2
内存布局是 xt40hZ$
1*** 11** *S{%+1F
1111 **** w{Dk,9>w)
1111 1111 yjN|PqtSV
,D~C40f
所以答案就是24和3 )/f,.Z$
9-)oA+$
下面是一个测试的程序,试一试就知道了,我用的是VC2005 Q0nSOTQ
KWhw@y-5j@
#pragma pack(8) Ks!.$y:x
Po=)jkW
struct s1{ wCc:HfmjJ
short a; // 2 BYtes [O(78n$$
long b; // 4 Bytes >#c]rk:
}; $Ne#F+M9x
struct s2{ RI cA)I.
char c; // 1 Byte l=bB,7gL
s1 d; // 8 Bytes q6/ o.j
long long e; // 8 Bytes R-hqaEB
}; [YJP
// 1*** 11** j s7J#b7
// 1111 **** hIPDJ1a
// 1111 1111 N.BD]_C
// )SUT+x(DU
g2 4)GjDi
// 00 01 02 03 04 05 06 07 )Q(tryiSi
// 00 01 02 03 04 05 06 07 3]<$;[Q
// 00 01 02 03 04 05 06 07 Y.jg
}oV
// S 8h/AW6l
#pragma pack() hGD7/qTN
Lj({
T'f(
int main(int argc, char* argv[]) Bn47O~
{ q^Oq:l$s
s2 a; :uhvDYp(-
char *p = (char *)&a; o&gcFOM22
for(int i=0;i<24;++i) OFCkQEG=y>
p = (char)(i%8); 42tD$S5^
printf("%d\n",sizeof(a)); N;RZIg(x
printf("c=0x%lx\n",a.c); >0:h(,?V
printf("d.a=0x%x\n",a.d.a); GEIMCg(TRj
printf("d.b=0x%x\n",a.d.b); %^gT.DsX-
printf("e=0x%llx\n",a.e); T(7
8{A>
return 0; u.8vXc
} #y}@FG
结果: K'N\"Y?>
24 9v<BO$
,a
c=0x0 LQNu]2
d.a=0x504 +z;xl-*[
d.b=0x3020100 GAtK1%nPD
e=0x706050403020100 >Mrz$
z{x
Af
^6
RYS]b[-xZz
网友 redleaves (ID最吊的网友)的答案和分析: kH1l -mxz
HSp*lHU
如果代码: _N9yC\
#pragma pack(8) M+)%gnq`u
struct S1{ 9BNAj-Xa
char a; iN+p>3w^l
long b; pRUN[[L
}; "`C|;\w
struct S2 { f1hi\p0q
char c; = J).(E89
struct S1 d; tN";o\!}
long long e; 5|S|HZ8G
}; BAdHGwomh
#pragma pack() ~ E>D0o
sizeof(S2)结果为24. % 49@
成员对齐有一个重要的条件,即每个成员分别对齐.即每个成员按自己的方式对齐. XV).
cW|.a
也就是说上面虽然指定了按8字节对齐,但并不是所有的成员都是以8字节对齐.其对齐的规则是,每个成员按其类型的对齐参数(通常是这个类型的大小)和指定对齐参数(这里是8字节)中较小的一个对齐.并且结构的长度必须为所用过的所有对齐参数的整数倍,不够就补空字节. /o+,
=7hY
JS}W4 N
S1中,成员a是1字节默认按1字节对齐,指定对齐参数为8,这两个值中取1,a按1字节对齐;成员b是4个字节,默认是按4字节对齐,这时就按4字节对齐,所以sizeof(S1)应该为8; |@Q(~[It
S2中,c和S1中的a一样,按1字节对齐,而d 是个结构,它是8个字节,它按什么对齐呢?对于结构来说,它的默认对齐方式就是它的所有成员使用的对齐参数中最大的一个,S1的就是4.所以,成员d就是按4字节对齐.成员e是8个字节,它是默认按8字节对齐,和指定的一样,所以它对到8字节的边界上,这时,已经使用了12个字节了,所以又添加了4个字节的空,从第16个字节开始放置成员e.这时,长度为24,已经可以被8(成员e按8字节对齐)整除.这样,一共使用了24个字节. NVeb,Pf
a b L~I<y;x
S1的内存布局:11**,1111, PIB|&I|p
c S1.a S1.b d ^X[Kr=:Jp
S2的内存布局:1***,11**,1111,****11111111 V*U"OJ%
NT= ?@uxD
这里有三点很重要: f==o
1.每个成员分别按自己的方式对齐,并能最小化长度 A<y3Tc?Q
2.复杂类型(如结构)的默认对齐方式是它最长的成员的对齐方式,这样在成员是复杂类型时,可以最小化长度 gC<\1AIu
3.对齐后的长度必须是成员中最大的对齐参数的整数倍,这样在处理数组时可以保证每一项都边界对齐 qSkt
}F%'
g^}X3NUn
@<W"$_r-
网友xue23(xue23) 的答案和分析: 5(u7b
3(E"$Se,f
有程序查一下各个变量的内存地址得知: g0cCw2S
各个变量在内存中的位置为 H Y.,f_m
c***aa** cS4e}\q,
bbbb**** +g7Iu! cA
dddddddd @hQ+pG@s
测试代码为: _Dwn@{[(8
s2 ss; PPPRO.y
cout << "ss.c = " << &ss << endl ; { tim{nV
cout << "ss.d.a = " <<&ss.d.a << endl; o
PR^Z
pt
cout << "ss.d.b = " <<&(ss.d.b) < cout << "ss.d = " <<&ss.e << endl; Ibd7[A\
print out 各个变量的内存地址不就可以看出来了吗。 jR}h3!
[-s0'z
所以答案是24,2. j%]i#iqF
AN$}%t"
但是我的想像中应该是这样的分布情况: .fUqsq
c******* FL(gwfL
aa**bbbb O 4l[4,`
dddddddd _GI [SzD
VqVP5nT'=
不知为什么会c和a放在一起,组成8位长度。