Intel和微软同时出现的C语言面试题 t>2^!vl
#pragma pack(8) JY+[
}$1;<
struct s1{ '5U$`Xe1
short a; \xxVDr.
long b; F/SsiUBS
}; u&x K>7
NR&9:?
struct s2{ |mmG
s
char c; 9VE;I:NO3
s1 d; ELF`uWGE
long long e; WN#lfn8 7
}; X^5"7phI@
N08n/u&cr,
#pragma pack() ~bTae =FP
}GDG$QI]K&
问 mN
6`8
[
1.sizeof(s2) = ? c$kb0VR
2.s2的s1中的a后面空了几个字节接着是b? ^&H=dYcV>/
';,Bn9rv
Te}yQ= +
~+egu89'TU
如果您知道答案请在讨论中写出,以下是部份网友的答案,供参考: QCfpDE}
pHB35=p28
网友rwxybh(行云)的答案: je4&'vyU
内存布局是 _-J @$d%
1*** 11** j(C
UYm
1111 **** /^3oq]
1111 1111 BemkCj2
chmJ|
所以答案就是24和3 B8AzN9v&"N
|QOJ9~hxD
下面是一个测试的程序,试一试就知道了,我用的是VC2005 n qLAby_
4<<bk_7'
#pragma pack(8) |cGeL[
Vnj/>e3
struct s1{ %Rep6=K*$
short a; // 2 BYtes }K80G~O2<
long b; // 4 Bytes Y\e]2
}; ;c-
]bhBB
struct s2{ K6{bYho
char c; // 1 Byte pJIE@Q|hi
s1 d; // 8 Bytes CEuk1$
long long e; // 8 Bytes N@*wi"Q
}; Tj21YK.mk
// 1*** 11** QrckTO
// 1111 **** Eu/y">;v#
// 1111 1111 )ko{S[gG
// ;xO=Yhc+
D5!K<G?-K
// 00 01 02 03 04 05 06 07 fj-pNl6Gf
// 00 01 02 03 04 05 06 07 (vAv^A*i}
// 00 01 02 03 04 05 06 07 =Xy`"i{`(
// Sci4EGc
#pragma pack() PIEW \i
(#B^Hyz!
int main(int argc, char* argv[]) i<wU.JX&h
{ 3> \fP#oQ
s2 a; e(w/m(!Wny
char *p = (char *)&a; $FQcDo|[
for(int i=0;i<24;++i) HKiVEg
p = (char)(i%8); |5~wwL@LW7
printf("%d\n",sizeof(a)); nl'J.dJe
printf("c=0x%lx\n",a.c); G?1x+H;o5
printf("d.a=0x%x\n",a.d.a); |Sr\jUIWn
printf("d.b=0x%x\n",a.d.b); UOu6LD/|h
printf("e=0x%llx\n",a.e); VXkAFgO
return 0; 4aN+}TkH@G
} h7EUIlh"
结果: wrQydI
24 *9dV/TT~f[
c=0x0 CO:*x,6au
d.a=0x504 JN&MyA"
d.b=0x3020100 8B *E+f0
e=0x706050403020100 K}PvrcO1
>HcYVp~G
v~V;+S=gz
网友 redleaves (ID最吊的网友)的答案和分析: &@4.;u
Lf^5Eo/
5A
如果代码: m3xz=9Ve
#pragma pack(8) YER:ICQ
struct S1{ AZxrJ2G
char a; 5;FP.{+
long b; #)_J)/h
}; \;-=ODC
struct S2 { ;'=VrE6
char c; VLh%XoQx[
struct S1 d; r7Nu>[r5
long long e; J 16=!q()
}; ,VKQRmd
#pragma pack() %"l81z
sizeof(S2)结果为24. 4ef*9|^x#
成员对齐有一个重要的条件,即每个成员分别对齐.即每个成员按自己的方式对齐. /rIm7FW)
也就是说上面虽然指定了按8字节对齐,但并不是所有的成员都是以8字节对齐.其对齐的规则是,每个成员按其类型的对齐参数(通常是这个类型的大小)和指定对齐参数(这里是8字节)中较小的一个对齐.并且结构的长度必须为所用过的所有对齐参数的整数倍,不够就补空字节. ]`zjRRd
N@cMM1
S1中,成员a是1字节默认按1字节对齐,指定对齐参数为8,这两个值中取1,a按1字节对齐;成员b是4个字节,默认是按4字节对齐,这时就按4字节对齐,所以sizeof(S1)应该为8; n 5~=qQK2
S2中,c和S1中的a一样,按1字节对齐,而d 是个结构,它是8个字节,它按什么对齐呢?对于结构来说,它的默认对齐方式就是它的所有成员使用的对齐参数中最大的一个,S1的就是4.所以,成员d就是按4字节对齐.成员e是8个字节,它是默认按8字节对齐,和指定的一样,所以它对到8字节的边界上,这时,已经使用了12个字节了,所以又添加了4个字节的空,从第16个字节开始放置成员e.这时,长度为24,已经可以被8(成员e按8字节对齐)整除.这样,一共使用了24个字节. Az9X#h.vf
a b nU}~I)@V
S1的内存布局:11**,1111, <ZigCo w
c S1.a S1.b d DH\wDQ
S2的内存布局:1***,11**,1111,****11111111 $Hp.{jw
kU#:I9PO
这里有三点很重要: 0=OD?48<
1.每个成员分别按自己的方式对齐,并能最小化长度 GhqgRzX
2.复杂类型(如结构)的默认对齐方式是它最长的成员的对齐方式,这样在成员是复杂类型时,可以最小化长度 `GvA241
3.对齐后的长度必须是成员中最大的对齐参数的整数倍,这样在处理数组时可以保证每一项都边界对齐 [urH a
LKqRvPnh
KU+( YF$1
网友xue23(xue23) 的答案和分析: 6RH/V:YY
`0yb?Nk `:
有程序查一下各个变量的内存地址得知: HG3.~ 6X
各个变量在内存中的位置为 U:qF/%w
c***aa** T|;^.TZ
bbbb**** |.j^G2x
dddddddd /"(b.&
测试代码为: G3H#XK D
s2 ss; mYjf5
cout << "ss.c = " << &ss << endl ; ,q8(]n4
cout << "ss.d.a = " <<&ss.d.a << endl; 65lOX$*{-
cout << "ss.d.b = " <<&(ss.d.b) < cout << "ss.d = " <<&ss.e << endl; q^u1z|'Z
print out 各个变量的内存地址不就可以看出来了吗。 Ru)(dvk}S
U8YO0}_z
所以答案是24,2. L<0=giE
/ca(a\@R
但是我的想像中应该是这样的分布情况: PT mf
c******* Y.E?;iS
aa**bbbb --Oprl
dddddddd 9#u }^t
=Q@6c
不知为什么会c和a放在一起,组成8位长度。