Intel和微软同时出现的C语言面试题 fB1TFtAh
#pragma pack(8) 1PH:\0}
g7\,{Bw#E
struct s1{ ?S
Z1`.S
short a; 5%zXAQD=<
long b; Pq9|WV#F5/
}; yWDTjY/
jN31hDg<z
struct s2{ Z[Qza13lo
char c; rH8@69,B
s1 d; B9R(&<4
long long e; ^qGb%! l
}; %" D%:
gF?[rqz{
#pragma pack() A#8q2n270*
KLoE&ds
问 <TGn=>u
1.sizeof(s2) = ? t_z,>,BqJ
2.s2的s1中的a后面空了几个字节接着是b? }t9.N`xu
hRC
1Xu?(2;NF
*&BnF\?m
如果您知道答案请在讨论中写出,以下是部份网友的答案,供参考: V7d)S&*V
Z@a9mFI?
网友rwxybh(行云)的答案: E/M_lvQ
内存布局是 o*WY=
1*** 11** dCyqvg6u
1111 **** : _e#
1111 1111 Byl^?5
?BA]7M(,4
所以答案就是24和3 bmgn cwlz
$+JS&k/'m
下面是一个测试的程序,试一试就知道了,我用的是VC2005 &H}r%%|A
Wj|alH9<
#pragma pack(8) fyTAou6hI
Jn:ZYqc
struct s1{ dZ#&YG)?e
short a; // 2 BYtes {7u[1[L1
long b; // 4 Bytes j#r6b]k(Hv
}; C%d_@*82
struct s2{ `Z:R Ce^
char c; // 1 Byte N6K*d` o
s1 d; // 8 Bytes [x=jH>Y
long long e; // 8 Bytes Kl7WQg,XOi
}; PyVC}dUAX
// 1*** 11** %^sTU4D5
// 1111 **** o#) {1<0vg
// 1111 1111 *IgE)N>
// Z4<L$i;/jN
A?_ =K
// 00 01 02 03 04 05 06 07 L86n}+
P\
// 00 01 02 03 04 05 06 07 E )Gw0]G
// 00 01 02 03 04 05 06 07 2M#M"LHo
// Q!-
0xlx
#pragma pack() <,o>Wx*1C
W} WI; cI
int main(int argc, char* argv[]) ^b: (jI*l
{ .2d9?p3Y
s2 a; :w}{$v}#D;
char *p = (char *)&a; T134ZXqqz
for(int i=0;i<24;++i) ojYbR<jn9
p = (char)(i%8); 'z76Sa
printf("%d\n",sizeof(a)); sn7AR88M;
printf("c=0x%lx\n",a.c); f}g\D#`]/
printf("d.a=0x%x\n",a.d.a); Lg8nj< TF
printf("d.b=0x%x\n",a.d.b); *I}`dC[
printf("e=0x%llx\n",a.e); CYOI.#m2
return 0; db'/`JeK
b
} 4XVCHs(
结果: !.2<| 24
24 8.F~k~srA
c=0x0 *6HTV0jv
d.a=0x504 COH<Tj
d.b=0x3020100 J>fQNW!{
e=0x706050403020100 mF` B#
UOQEk22
c/c$D;T
网友 redleaves (ID最吊的网友)的答案和分析: }Zl&]e
21k5I #U
如果代码: r0p w_j
#pragma pack(8) YK|bXSA[
struct S1{ [MuEoWrq(}
char a; t78k4?
long b; wFG3KzEq ~
}; 8XbA'% o
struct S2 { @lJzr3}WZ
char c; {vAE:W.s
struct S1 d; $w"$r$K9K
long long e; + QQS={
}; 06jqQ-_`h
#pragma pack() hig2
sizeof(S2)结果为24. [+O"<Ua
成员对齐有一个重要的条件,即每个成员分别对齐.即每个成员按自己的方式对齐. GfM;saTz{
也就是说上面虽然指定了按8字节对齐,但并不是所有的成员都是以8字节对齐.其对齐的规则是,每个成员按其类型的对齐参数(通常是这个类型的大小)和指定对齐参数(这里是8字节)中较小的一个对齐.并且结构的长度必须为所用过的所有对齐参数的整数倍,不够就补空字节. C9p"?vX
THmb6^
S1中,成员a是1字节默认按1字节对齐,指定对齐参数为8,这两个值中取1,a按1字节对齐;成员b是4个字节,默认是按4字节对齐,这时就按4字节对齐,所以sizeof(S1)应该为8; y%
:4b@<
S2中,c和S1中的a一样,按1字节对齐,而d 是个结构,它是8个字节,它按什么对齐呢?对于结构来说,它的默认对齐方式就是它的所有成员使用的对齐参数中最大的一个,S1的就是4.所以,成员d就是按4字节对齐.成员e是8个字节,它是默认按8字节对齐,和指定的一样,所以它对到8字节的边界上,这时,已经使用了12个字节了,所以又添加了4个字节的空,从第16个字节开始放置成员e.这时,长度为24,已经可以被8(成员e按8字节对齐)整除.这样,一共使用了24个字节. 2]% h$f+
a b Bl=tYp|a
S1的内存布局:11**,1111, 9UvXC)R1
c S1.a S1.b d mPq$?gdp
S2的内存布局:1***,11**,1111,****11111111 wAnb
Di{W
!w&kyW?e
这里有三点很重要: 2^?:&1:
1.每个成员分别按自己的方式对齐,并能最小化长度 v4@Z(M
2.复杂类型(如结构)的默认对齐方式是它最长的成员的对齐方式,这样在成员是复杂类型时,可以最小化长度 cwGbSW$t
3.对齐后的长度必须是成员中最大的对齐参数的整数倍,这样在处理数组时可以保证每一项都边界对齐 t&?im<
bWOS `5
re> rr4@
网友xue23(xue23) 的答案和分析: ?%H):r
Y@PI {;!
有程序查一下各个变量的内存地址得知: cQ9q;r`%
各个变量在内存中的位置为 {Zp\^/
c***aa** asJ)4ema
bbbb**** L(X6-M:
dddddddd KK@.~'d
测试代码为: N!*_La=TuH
s2 ss; `^lYw:xA
cout << "ss.c = " << &ss << endl ; S_~z-`;h!
cout << "ss.d.a = " <<&ss.d.a << endl; qCv20#!"|
cout << "ss.d.b = " <<&(ss.d.b) < cout << "ss.d = " <<&ss.e << endl; :;t
#\%L/
print out 各个变量的内存地址不就可以看出来了吗。 uc|45Zxt
xe/(
所以答案是24,2. *L!!]Q2c
[s<^&WM/
但是我的想像中应该是这样的分布情况: L~ s3b
c******* .^b;osAU
aa**bbbb Rb\6;i8R
dddddddd WJ*n29^N^h
5xii(\lC
不知为什么会c和a放在一起,组成8位长度。