Intel和微软同时出现的C语言面试题 {bR2S&=OmK
#pragma pack(8) Gz BPI'C
;^u,[d
struct s1{ ' Ttsscv
short a; 6yO5{._M
long b; ecQ{ePoU
}; znSlSQpTv
N{~P}Sw
struct s2{ ij!],
char c; NbTaI{r
s1 d; Sc#3<nVg
long long e; M@P%k`6C
}; j"hEs(t
*v]s&$WyO
#pragma pack() /-i m
g^^
|TP,
问 @x!,iT
1.sizeof(s2) = ? `/'p1?Z"
2.s2的s1中的a后面空了几个字节接着是b? ~,E }^
K*{RGE
:CK`v6 Qs
,msP(*qoI
如果您知道答案请在讨论中写出,以下是部份网友的答案,供参考: sW'_K.z
Wh)
网友rwxybh(行云)的答案: Kw$@_~BJ6
内存布局是 {g1"{
1*** 11** xBc|rqge
1111 **** hvO$ f.i
1111 1111 |[iO./zP
'}(>s%~
所以答案就是24和3 "GZ}+K*GG
cL*oO@I&_
下面是一个测试的程序,试一试就知道了,我用的是VC2005 y7:f^4
?2da6v,t
#pragma pack(8) _[z)%`kay
(0Br`%!F
struct s1{ kP[fhOpn
short a; // 2 BYtes |3E|VGm~
long b; // 4 Bytes 4[x`\
}; x3FB`3y~s
struct s2{ %G2g
@2
char c; // 1 Byte Xw'sh#i2
s1 d; // 8 Bytes :Bt,.uNC
long long e; // 8 Bytes [Z2[Iy
}; $dKfUlO
// 1*** 11** 2HBey
// 1111 **** "IQYy~
/
// 1111 1111 /cx'(AT
// .wq
j
2>^(&95M
// 00 01 02 03 04 05 06 07 zF^H*H
// 00 01 02 03 04 05 06 07 e8dZR3JL
// 00 01 02 03 04 05 06 07 5lD`qY
// ^.)0O3oC
#pragma pack() qzvht4
eDP&W$s#
int main(int argc, char* argv[]) qonStIP
{ @.a59kP8X
s2 a; !ck~4~J
char *p = (char *)&a; 3]9wfT%d
for(int i=0;i<24;++i) $eT[`r
p = (char)(i%8); z7XI`MZN^
printf("%d\n",sizeof(a)); l
lcq~*zz
printf("c=0x%lx\n",a.c); s 7wA3|9
printf("d.a=0x%x\n",a.d.a); /*fx`0mY)
printf("d.b=0x%x\n",a.d.b); -a>CF^tH
printf("e=0x%llx\n",a.e); X6Z/xb@
return 0; `u_MdB}<x;
} zQ,M795@EA
结果: XX90Is
24 "2-D[rYZ
c=0x0 PE6,9i0ee
d.a=0x504 XY6Sm{
d.b=0x3020100 |P&
\C8h
e=0x706050403020100 /mp!%j~
-wx~*
'j{o!T0
网友 redleaves (ID最吊的网友)的答案和分析: OY81|N
j
LU8[$.P
如果代码: `_1fa7,z
#pragma pack(8) >h~ik/|*
struct S1{ X!~y&[;[C
char a; 4HZXv\$
long b; 7D>_<)%d=
}; 98
NFJ
struct S2 { PU%f`)
char c; ?5B?P:=kl
struct S1 d; M~`^deU1
long long e; X-"
+nThMn
}; u.n'dF-
#pragma pack() \i-CTv6f
sizeof(S2)结果为24. iyR"O1]
成员对齐有一个重要的条件,即每个成员分别对齐.即每个成员按自己的方式对齐. `S-%}eUv
也就是说上面虽然指定了按8字节对齐,但并不是所有的成员都是以8字节对齐.其对齐的规则是,每个成员按其类型的对齐参数(通常是这个类型的大小)和指定对齐参数(这里是8字节)中较小的一个对齐.并且结构的长度必须为所用过的所有对齐参数的整数倍,不够就补空字节. cVMRSp
-~(d_
S1中,成员a是1字节默认按1字节对齐,指定对齐参数为8,这两个值中取1,a按1字节对齐;成员b是4个字节,默认是按4字节对齐,这时就按4字节对齐,所以sizeof(S1)应该为8; C,mfA%63
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@+$lU*r
a b @^ &p$:
S1的内存布局:11**,1111, 0:I<TJ~P
c S1.a S1.b d IaOR%Bg
S2的内存布局:1***,11**,1111,****11111111 @T L|\T
%LmsywPPp
这里有三点很重要: h0dZr-c
1.每个成员分别按自己的方式对齐,并能最小化长度 e9/Mjq\
2.复杂类型(如结构)的默认对齐方式是它最长的成员的对齐方式,这样在成员是复杂类型时,可以最小化长度 :/$_eg0A
3.对齐后的长度必须是成员中最大的对齐参数的整数倍,这样在处理数组时可以保证每一项都边界对齐 umnQ$y
0
QT!>izgcU
NMhpKno
网友xue23(xue23) 的答案和分析: #rr!ApJ
uF}B:53A
有程序查一下各个变量的内存地址得知: [MbbL
各个变量在内存中的位置为 R)SY#*Y
c***aa** q7soV(P
bbbb**** H =~7g3
dddddddd zv;xxAX
测试代码为: 1$C?+H
s2 ss; P{QHG 3
cout << "ss.c = " << &ss << endl ; .Oc j|A6
cout << "ss.d.a = " <<&ss.d.a << endl; ?D)$OCS
cout << "ss.d.b = " <<&(ss.d.b) < cout << "ss.d = " <<&ss.e << endl; *pnaj\
print out 各个变量的内存地址不就可以看出来了吗。 xqY'-Hom
B@dCCKc%/
所以答案是24,2. 6:; >id${
:HY =^$\
但是我的想像中应该是这样的分布情况: b$*2bSdv0<
c******* jC}HNiM78
aa**bbbb ;;Z'd@
dddddddd kF,ME5%
Hsv)]
%p
不知为什么会c和a放在一起,组成8位长度。