Intel和微软同时出现的C语言面试题 $(8CU$gi=
#pragma pack(8) DYFfq
<@z!kl
struct s1{ HXp$\%A)
short a; txp^3dZ`^
long b; 78fFAN`
}; 7)#8p@Q
jZ\a:K?
struct s2{ 5.3=2/
char c; 84eqT[I'
s1 d; Tz?0E"yx
long long e; 70BLd(?
}; 7uW=f kxT
Uop`)
#pragma pack() sOUQd-!"
nWz7$O
问 {oK4
u
1.sizeof(s2) = ? |)}&:xA%
2.s2的s1中的a后面空了几个字节接着是b? Ufr,6IX
s7>a
;*}tbh3;.
|s$w
i>7l
如果您知道答案请在讨论中写出,以下是部份网友的答案,供参考: Z_.xglq{
L.tW]43K
网友rwxybh(行云)的答案: fS#I?!*}
内存布局是 6(0ME$
1*** 11** 8.m9 =+)8
1111 **** ]w;!x7bU(
1111 1111 9 m`VIB
]]^eIjg>a6
所以答案就是24和3 "vL,c]D
l}MVk%[
下面是一个测试的程序,试一试就知道了,我用的是VC2005 ,z0~VS:g 8
'YTSakNJ}
#pragma pack(8) &b:SDl6
:qe.*\
c
struct s1{ s i=m5$V
short a; // 2 BYtes z<u*I@;
long b; // 4 Bytes Xdtyer%
}; EwX:^1f
struct s2{ rctGa ,l
char c; // 1 Byte :.bBV]6q
s1 d; // 8 Bytes .Gq]Mrim9G
long long e; // 8 Bytes +Cg[!6[#
}; = Y`e?\#`
// 1*** 11** Lsb` ,:
// 1111 **** 7Z[6_WD3
// 1111 1111 h51)kN:
// O@-|_N*;K
d;FOmo4
// 00 01 02 03 04 05 06 07 {
d |lN:B
// 00 01 02 03 04 05 06 07 W|-<ekH_u
// 00 01 02 03 04 05 06 07 Q8
// 5BRZpCb
#pragma pack() #)b0&wyW6i
Pof]9qE-y
int main(int argc, char* argv[]) }LTy Xo
{ 'M!* Ge
s2 a; ;@$v_i
char *p = (char *)&a; G A+#'R
for(int i=0;i<24;++i) '"M9`@Y3^
p = (char)(i%8); _A]=45cn~
printf("%d\n",sizeof(a)); s9F{UN3
printf("c=0x%lx\n",a.c); k!)Pl,nJ
printf("d.a=0x%x\n",a.d.a); 'D &[Y)f^
printf("d.b=0x%x\n",a.d.b); |B~^7RHXo
printf("e=0x%llx\n",a.e); |$+
xVi8
return 0; 1}ER+;If
} PDNbhUAV
结果: G{]tB w
24 >1S39n5z.
c=0x0 =s/UF _JN
d.a=0x504 we}G%09L
d.b=0x3020100 N SkIzaNY
e=0x706050403020100 'gv~M_
|kK_B
:K
26B+qXEt
网友 redleaves (ID最吊的网友)的答案和分析: 94Q?)0W$
q)Qg'l^f
如果代码: *wp>a?sG\
#pragma pack(8) _Y _v&
struct S1{ C2(VYw
char a; fq4[/%6,O
long b; h;DLD8L
}; w
tSX(LNY
struct S2 { m4x8W2q
char c; iOXsj
struct S1 d; 8d1r#sILI
long long e; ,
G9{:
}; >eM>Y@8=
#pragma pack() A3eus
sizeof(S2)结果为24. b`&
:`
成员对齐有一个重要的条件,即每个成员分别对齐.即每个成员按自己的方式对齐. RcpKv;= iB
也就是说上面虽然指定了按8字节对齐,但并不是所有的成员都是以8字节对齐.其对齐的规则是,每个成员按其类型的对齐参数(通常是这个类型的大小)和指定对齐参数(这里是8字节)中较小的一个对齐.并且结构的长度必须为所用过的所有对齐参数的整数倍,不够就补空字节. ,,+iPGa<
Wi<g
S1中,成员a是1字节默认按1字节对齐,指定对齐参数为8,这两个值中取1,a按1字节对齐;成员b是4个字节,默认是按4字节对齐,这时就按4字节对齐,所以sizeof(S1)应该为8; Yc p<N>)
S2中,c和S1中的a一样,按1字节对齐,而d 是个结构,它是8个字节,它按什么对齐呢?对于结构来说,它的默认对齐方式就是它的所有成员使用的对齐参数中最大的一个,S1的就是4.所以,成员d就是按4字节对齐.成员e是8个字节,它是默认按8字节对齐,和指定的一样,所以它对到8字节的边界上,这时,已经使用了12个字节了,所以又添加了4个字节的空,从第16个字节开始放置成员e.这时,长度为24,已经可以被8(成员e按8字节对齐)整除.这样,一共使用了24个字节. P TMJ.;
a b v\3$$T)
S1的内存布局:11**,1111, ul^VGW>i
c S1.a S1.b d #M@Ki1
S2的内存布局:1***,11**,1111,****11111111 |* v w(
@ebSM#F?
这里有三点很重要: k@}g?X`8
1.每个成员分别按自己的方式对齐,并能最小化长度 L =9^Y/8Q
2.复杂类型(如结构)的默认对齐方式是它最长的成员的对齐方式,这样在成员是复杂类型时,可以最小化长度 &e)V!o@wJV
3.对齐后的长度必须是成员中最大的对齐参数的整数倍,这样在处理数组时可以保证每一项都边界对齐 P&sYS<9q
B2T=O %
2#)z%K6T
网友xue23(xue23) 的答案和分析: ioJ|-@!#o
#,CK;h9jy!
有程序查一下各个变量的内存地址得知: V)jF]u~g
各个变量在内存中的位置为 E'+?7ZGWj
c***aa** Zonr/sA ~
bbbb**** d*R('0z{
dddddddd @XQItc<
测试代码为: 8>AST,
s2 ss; V(wANvH
cout << "ss.c = " << &ss << endl ; 0x,NMS
cout << "ss.d.a = " <<&ss.d.a << endl; hQ\W~3S55
cout << "ss.d.b = " <<&(ss.d.b) < cout << "ss.d = " <<&ss.e << endl; 1w} DfI
print out 各个变量的内存地址不就可以看出来了吗。 T
)!kJ;vc
JIU8~D
所以答案是24,2. }s@vN8C
k] iyx
但是我的想像中应该是这样的分布情况: oef]
c******* <~}NxY\5
aa**bbbb TrR=3_;.7
dddddddd cm17hPe`}n
e N^6gub
不知为什么会c和a放在一起,组成8位长度。