Intel和微软同时出现的C语言面试题 VtzI9CD
#pragma pack(8) !
iptT(2
,g7.rEA
struct s1{ -b9;5eS!
short a; C w~RJ^a_
long b; 4q'B<7{Q
}; G0`h %
o\88t){/kB
struct s2{ UK$ms~H
char c; ~go
fQ
s1 d; B!dU>0&Ct
long long e; Y 2Q=rj
}; V7Z4T6j4
@WQK>-=(3
#pragma pack() ,bM-I2BR
) c/%
NiN
问 Q~MC7-n>
1.sizeof(s2) = ? $xOI 1|d
2.s2的s1中的a后面空了几个字节接着是b? LAP6U.m'd
BnCKSg7V
Fi.aC;sx
<W`#gn0b6
如果您知道答案请在讨论中写出,以下是部份网友的答案,供参考: 28hHabd|
DbZ0e5
网友rwxybh(行云)的答案: 6vp *9
内存布局是 $B#6tk~u
1*** 11** l"{Sm6:;-
1111 **** FYb34LY
1111 1111 qC_mu)6
-w;(cE
所以答案就是24和3 o7TN,([W
p1D[YeF4
下面是一个测试的程序,试一试就知道了,我用的是VC2005 X; 5Jb
FVB;\'/
#pragma pack(8) D?~8za`5
uK("<u|
struct s1{ {/LZcz[
short a; // 2 BYtes ?f*Q>3S)
long b; // 4 Bytes 6cdMS[_SD(
}; B_ja&) !s1
struct s2{ tp:\j@dB
char c; // 1 Byte FP#FB$eP
s1 d; // 8 Bytes C{Asp
long long e; // 8 Bytes e8h,,:l3j
}; 2/36dGFH
// 1*** 11** DY{cQb
// 1111 **** "o&HE@t
// 1111 1111 Z?NEO>h7
// 1z*kc)=JF8
%d m-?`
// 00 01 02 03 04 05 06 07 ++}\v9Er
// 00 01 02 03 04 05 06 07 Q<6P. PTya
// 00 01 02 03 04 05 06 07 {%.Lk'#9
// H@l}[hkP
#pragma pack() C}?0`!Cc%
m7=1%6FN3
int main(int argc, char* argv[]) WlV
z,t'if
{ j2M+]Zp.
s2 a; .mL#6P!d3^
char *p = (char *)&a; _M,lQ~
for(int i=0;i<24;++i) ~|Z'l%<Os
p = (char)(i%8); "R9Yb,tIN
printf("%d\n",sizeof(a)); m"-[".-l-
printf("c=0x%lx\n",a.c); PfG`C5
d
printf("d.a=0x%x\n",a.d.a); Y'`"9Db
printf("d.b=0x%x\n",a.d.b); Q0_>'sEM
printf("e=0x%llx\n",a.e); 6+dn*_[Z6
return 0; PoShQR<
} +VU4s$w6
结果: -Dzsa
24 ,Vd7V}t
c=0x0 kw,$NK'
d.a=0x504 >qn/<??
d.b=0x3020100 Qu%D
e=0x706050403020100 %G?K@5?j?
XidxNPz0^
pKJK9@Ad
网友 redleaves (ID最吊的网友)的答案和分析: ad n|N
/&Jv,[2kV
如果代码: sI 4yG
#pragma pack(8) ujgLJ77
struct S1{ MZ#T^Y
char a; t7F.[uWD
long b; UP2.]B!d
}; 8NimZ(
struct S2 { :#="%
char c; TYjA:d9YH
struct S1 d;
FfM nul
long long e; yu&Kh4AP
}; X QbNH~
#pragma pack() GVd48 *
sizeof(S2)结果为24. (TSqc5^H
成员对齐有一个重要的条件,即每个成员分别对齐.即每个成员按自己的方式对齐. LxJ6M/".
也就是说上面虽然指定了按8字节对齐,但并不是所有的成员都是以8字节对齐.其对齐的规则是,每个成员按其类型的对齐参数(通常是这个类型的大小)和指定对齐参数(这里是8字节)中较小的一个对齐.并且结构的长度必须为所用过的所有对齐参数的整数倍,不够就补空字节. FWPW/oC
hSqMaX%G
S1中,成员a是1字节默认按1字节对齐,指定对齐参数为8,这两个值中取1,a按1字节对齐;成员b是4个字节,默认是按4字节对齐,这时就按4字节对齐,所以sizeof(S1)应该为8; ;R[&pDx
S2中,c和S1中的a一样,按1字节对齐,而d 是个结构,它是8个字节,它按什么对齐呢?对于结构来说,它的默认对齐方式就是它的所有成员使用的对齐参数中最大的一个,S1的就是4.所以,成员d就是按4字节对齐.成员e是8个字节,它是默认按8字节对齐,和指定的一样,所以它对到8字节的边界上,这时,已经使用了12个字节了,所以又添加了4个字节的空,从第16个字节开始放置成员e.这时,长度为24,已经可以被8(成员e按8字节对齐)整除.这样,一共使用了24个字节. 6E9N(kFYs
a b #i@h{R01
S1的内存布局:11**,1111, y7zkAXhJ
c S1.a S1.b d 4/wwn6I}G
S2的内存布局:1***,11**,1111,****11111111 @?2n]n6
a&/HSf_G
这里有三点很重要: [}""@?
1.每个成员分别按自己的方式对齐,并能最小化长度 T$b\Q
2.复杂类型(如结构)的默认对齐方式是它最长的成员的对齐方式,这样在成员是复杂类型时,可以最小化长度 PM~*|(fA
3.对齐后的长度必须是成员中最大的对齐参数的整数倍,这样在处理数组时可以保证每一项都边界对齐 qj?2%mK`
dl[ob,aCK
(iDBhC;/B
网友xue23(xue23) 的答案和分析: b%0BkS*
LZ&uj{ <
有程序查一下各个变量的内存地址得知: lL2-.!]R
各个变量在内存中的位置为 kMe@+ysL
c***aa** tSw>@FM
bbbb**** #)i&DJ^Y
dddddddd &X w`T9<
测试代码为: 4%bTj,H#
s2 ss; d)*(KhYie@
cout << "ss.c = " << &ss << endl ; J'7 y
cout << "ss.d.a = " <<&ss.d.a << endl; x*mc - &N
cout << "ss.d.b = " <<&(ss.d.b) < cout << "ss.d = " <<&ss.e << endl; z<QIuq
print out 各个变量的内存地址不就可以看出来了吗。 ku3D?D:V
*98Ti|
所以答案是24,2. {(HxG4~
j:?N!*r=
但是我的想像中应该是这样的分布情况: BD1K H;
c******* FuMq|S
aa**bbbb 3L fTGO
dddddddd F^TAd
T+W3_xIS X
不知为什么会c和a放在一起,组成8位长度。