Intel和微软同时出现的C语言面试题 /E)9v$!
#pragma pack(8) i#k-)N _$
H \ 3M
struct s1{ _HwpPRVP/
short a; ]22C)<
long b; qc3~cH.@
}; ])C>\@c6Gm
>b'w'"
struct s2{ qB+n6y%
char c; fVYiwE=F
s1 d; LaDY`u0G%
long long e; 9J?W '8s5
}; P2Onkl
kg:l:C)Tq
#pragma pack() s,w YlVYf!
9GThyY
问 0Su_#".-*
1.sizeof(s2) = ? 9X3yp:>V
2.s2的s1中的a后面空了几个字节接着是b? \4aKLr
Y:wF5pp;
Khj=llo,
h77IWo6%
如果您知道答案请在讨论中写出,以下是部份网友的答案,供参考: )Lb72;!?
8\DME
网友rwxybh(行云)的答案: w$b~x4y%
内存布局是 ^+M><jE9
1*** 11** }?J~P%HpF
1111 **** 82|q7*M*.
1111 1111 |ixGY^3;
}hCaNQ&jH
所以答案就是24和3 Ss 2$n
Z9xR
下面是一个测试的程序,试一试就知道了,我用的是VC2005 ^PC\E}
~Yl<S(/4
#pragma pack(8) P])L8zK
dN<5JQql
struct s1{ wk@yTTnb
short a; // 2 BYtes ^T{8uJ'kn
long b; // 4 Bytes }C_|gd
}; Yq
J]7V\
struct s2{ [.a;L">
char c; // 1 Byte o_O+u%y
s1 d; // 8 Bytes EX4
C.C|d
long long e; // 8 Bytes '6X%=f'^b
}; <Pio Q>~
// 1*** 11** z>|)ieL
// 1111 **** .liyC~YW
// 1111 1111 *="m3:c'J
// 9\>sDSCx
iD<6t_8),
// 00 01 02 03 04 05 06 07 \e|U9;Mf
// 00 01 02 03 04 05 06 07 izf~w^/
// 00 01 02 03 04 05 06 07 9Eg&CZ,9$D
// VJg,~lQN#t
#pragma pack() 7G"7wYc>R
,%Z&*n
int main(int argc, char* argv[]) AFm,CINa
{ XIRR Al(,
s2 a; }%x}fu#
char *p = (char *)&a; gD6tHg>_
for(int i=0;i<24;++i) V!xwb:J
p = (char)(i%8); ;R!*I%
printf("%d\n",sizeof(a)); Mn@$;\:
printf("c=0x%lx\n",a.c); xg} ug[
printf("d.a=0x%x\n",a.d.a); <BPRV> 0X
printf("d.b=0x%x\n",a.d.b); 6JH56
printf("e=0x%llx\n",a.e); YDFCGA
return 0; XVF^,Yf
} ]`d2_mu
结果: f^?uY8<
24 ;E#\
c=0x0 (z2Z)_6L*L
d.a=0x504 `NSy"6{Z
d.b=0x3020100 %[ /<+
e=0x706050403020100 sB6dpD
~:EW>Fq%i
^dfx~C
网友 redleaves (ID最吊的网友)的答案和分析: f ;wc{qy
xr.XU'
如果代码: ~ezCu_
#pragma pack(8) q@kOTkHv)
struct S1{ B+Z13;}B
char a; .=XD)>$
long b; 7)J6/('
}; {a@>6)
struct S2 { q^*6C[G B
char c; E/mw* c^
struct S1 d; `hzrfum4
long long e; 2tf6GX:
}; xnbsg!`;7W
#pragma pack() g~!$i`_b
sizeof(S2)结果为24. vCb]%sd-U
成员对齐有一个重要的条件,即每个成员分别对齐.即每个成员按自己的方式对齐. q}wj}t#
也就是说上面虽然指定了按8字节对齐,但并不是所有的成员都是以8字节对齐.其对齐的规则是,每个成员按其类型的对齐参数(通常是这个类型的大小)和指定对齐参数(这里是8字节)中较小的一个对齐.并且结构的长度必须为所用过的所有对齐参数的整数倍,不够就补空字节. c
0-w6
)o jDRJ&
S1中,成员a是1字节默认按1字节对齐,指定对齐参数为8,这两个值中取1,a按1字节对齐;成员b是4个字节,默认是按4字节对齐,这时就按4字节对齐,所以sizeof(S1)应该为8; hwVAXsF~
S2中,c和S1中的a一样,按1字节对齐,而d 是个结构,它是8个字节,它按什么对齐呢?对于结构来说,它的默认对齐方式就是它的所有成员使用的对齐参数中最大的一个,S1的就是4.所以,成员d就是按4字节对齐.成员e是8个字节,它是默认按8字节对齐,和指定的一样,所以它对到8字节的边界上,这时,已经使用了12个字节了,所以又添加了4个字节的空,从第16个字节开始放置成员e.这时,长度为24,已经可以被8(成员e按8字节对齐)整除.这样,一共使用了24个字节. h!e2
+4{4{
a b J &{xP8uq_
S1的内存布局:11**,1111, *d>vR1
c S1.a S1.b d eh<rRx"[
S2的内存布局:1***,11**,1111,****11111111 ]*;F. pZ
Go <'
这里有三点很重要: 7F(5)Utt
1.每个成员分别按自己的方式对齐,并能最小化长度 V7C1FV2
2.复杂类型(如结构)的默认对齐方式是它最长的成员的对齐方式,这样在成员是复杂类型时,可以最小化长度 :6lwO%=F
3.对齐后的长度必须是成员中最大的对齐参数的整数倍,这样在处理数组时可以保证每一项都边界对齐 yU7I;]YP
k|FSz#Y
Jq
.L:>x
网友xue23(xue23) 的答案和分析: 5+K;_)
J?%}=_fsa
有程序查一下各个变量的内存地址得知: -=)-s m'
各个变量在内存中的位置为 q8sbn
c***aa** ,J(lJ,c
bbbb**** S0LszW)e
dddddddd hD
q2-X}
测试代码为: -eml
s2 ss; .X'<
D*
cout << "ss.c = " << &ss << endl ; }fA;7GW+9
cout << "ss.d.a = " <<&ss.d.a << endl; ?z=\Ye5x
cout << "ss.d.b = " <<&(ss.d.b) < cout << "ss.d = " <<&ss.e << endl; U=cWmH
print out 各个变量的内存地址不就可以看出来了吗。 QU/3X 1W
a2yE:16o6
所以答案是24,2. eN/G i<
OVR?*"N_
但是我的想像中应该是这样的分布情况: 1h=D4yN
c******* z(H?VfJo
aa**bbbb q4ipumy*
dddddddd =yqHC<8:
i8~r
不知为什么会c和a放在一起,组成8位长度。