Intel和微软同时出现的C语言面试题 :1
#pragma pack(8) 0r&9AnnWu+
`-`iS?
struct s1{ i(;u6Rk
short a; |>V>6%>vK6
long b; 'r <BaL
}; ':>*=&
J]YN2{(x
struct s2{ PSw+E';
char c; <Q~7a
hF
s1 d; xa^HU~
long long e; Qy,qQA/
}; M|]1}8d?
8$olP:d
#pragma pack() H/I`c>Zn
s3%8W==rBW
问 @*{BX~f
1.sizeof(s2) = ? Hjkgy%N
2.s2的s1中的a后面空了几个字节接着是b? u1Yp5jp^K
W {/z-&
j %0_!*#3
h\ek2K
如果您知道答案请在讨论中写出,以下是部份网友的答案,供参考: ,H1~_|)<
FDC{8e
网友rwxybh(行云)的答案: 0'oT {iN
内存布局是 oeKc-[r
1*** 11** D6:J*F&?
1111 **** 2^lT!X@
1111 1111 ?pY!sG
==r|]~x
所以答案就是24和3 NX", e=
!\uk b
下面是一个测试的程序,试一试就知道了,我用的是VC2005 /pN2Jst
Wm&f+{LO+K
#pragma pack(8) + # >%bq x
AWNd(B2o
struct s1{ G{Q'N04RA
short a; // 2 BYtes <LZvh8
long b; // 4 Bytes mR@Xt#
}; n?tAa|_
struct s2{ Y% 9F
char c; // 1 Byte D/`E!6Fk=
s1 d; // 8 Bytes Kn\(Xd.>
long long e; // 8 Bytes za/#R_%p
}; B)`X7uG
// 1*** 11** rl7Y=*Dv
// 1111 **** ]vFmY
// 1111 1111 I]$d,N!.
// _Q}z 6+_\
?{IvA:
// 00 01 02 03 04 05 06 07 Z.(x|Q9
// 00 01 02 03 04 05 06 07 M.Ik%nN#K0
// 00 01 02 03 04 05 06 07 ;^i,Q} b/
// RV(z>XM
#pragma pack() m~B=C>r}t
}O{"qs#)
int main(int argc, char* argv[]) Al]9/ML/m
{ Q7%#3ML
s2 a; 8hp]+k_y
char *p = (char *)&a; YTh4&wm
for(int i=0;i<24;++i) eP?|U.on
p = (char)(i%8); &Hxr3[+$
printf("%d\n",sizeof(a)); rI789q
printf("c=0x%lx\n",a.c); [DEw:%
printf("d.a=0x%x\n",a.d.a); m m`3-F|
printf("d.b=0x%x\n",a.d.b); Tq8r
SZi
printf("e=0x%llx\n",a.e); N9<eU!4>
return 0; lukV
G2wDL
} #"JU39e
结果: R<Tzt'z
24 bb/MnhB
c=0x0 A'EA !
d.a=0x504 :i$Z
d.b=0x3020100 Fgk/Ph3r
e=0x706050403020100 [9^e
u>)A
1hG O*cq!
BI]t}7
网友 redleaves (ID最吊的网友)的答案和分析: WG{/I/bJ_
mio'm
如果代码: cf'Z#NfQ
#pragma pack(8) ?Gfe?
struct S1{ OpE+e4~IF
char a; (?[cDw/{J:
long b; '3->G/Pu
}; N~d]}J8}gx
struct S2 { P|U>(9;P,
char c; ')V5hKb^
struct S1 d; -y(V-
long long e; B=Os?'2[
}; 0]~n8mB>
#pragma pack() .Ps;O
sizeof(S2)结果为24. ^D|c
成员对齐有一个重要的条件,即每个成员分别对齐.即每个成员按自己的方式对齐. Yw<:I&
也就是说上面虽然指定了按8字节对齐,但并不是所有的成员都是以8字节对齐.其对齐的规则是,每个成员按其类型的对齐参数(通常是这个类型的大小)和指定对齐参数(这里是8字节)中较小的一个对齐.并且结构的长度必须为所用过的所有对齐参数的整数倍,不够就补空字节. 8=9sIK2
]FBfh.#X@
S1中,成员a是1字节默认按1字节对齐,指定对齐参数为8,这两个值中取1,a按1字节对齐;成员b是4个字节,默认是按4字节对齐,这时就按4字节对齐,所以sizeof(S1)应该为8; c`QsKwa
S2中,c和S1中的a一样,按1字节对齐,而d 是个结构,它是8个字节,它按什么对齐呢?对于结构来说,它的默认对齐方式就是它的所有成员使用的对齐参数中最大的一个,S1的就是4.所以,成员d就是按4字节对齐.成员e是8个字节,它是默认按8字节对齐,和指定的一样,所以它对到8字节的边界上,这时,已经使用了12个字节了,所以又添加了4个字节的空,从第16个字节开始放置成员e.这时,长度为24,已经可以被8(成员e按8字节对齐)整除.这样,一共使用了24个字节. NM Ajt>t
a b zOw]P6Gk
S1的内存布局:11**,1111, 8hg(6 XUG
c S1.a S1.b d
(~oPr+d
S2的内存布局:1***,11**,1111,****11111111 Vi_|m?E
8ic_|hfY
这里有三点很重要: /H%pOL6(r
1.每个成员分别按自己的方式对齐,并能最小化长度 QPEv@laM
2.复杂类型(如结构)的默认对齐方式是它最长的成员的对齐方式,这样在成员是复杂类型时,可以最小化长度 jp]JFh;3
3.对齐后的长度必须是成员中最大的对齐参数的整数倍,这样在处理数组时可以保证每一项都边界对齐 %9.KH
AF-.Nwp
RYNzTA
网友xue23(xue23) 的答案和分析: H>]x<#uz)
=$Z'F<|d
有程序查一下各个变量的内存地址得知: OUPpz_y
各个变量在内存中的位置为 ?6bE!36
c***aa** <k!G%R<9
bbbb**** _p.{|7
dddddddd 4E)[<%
测试代码为: $;1~JOZh
s2 ss; 9[*kpMC
cout << "ss.c = " << &ss << endl ; \=<.0K A~
cout << "ss.d.a = " <<&ss.d.a << endl; 6>Y}2fT}o3
cout << "ss.d.b = " <<&(ss.d.b) < cout << "ss.d = " <<&ss.e << endl; iC]}M
print out 各个变量的内存地址不就可以看出来了吗。 voxlo>:
#a&Vx&7L
所以答案是24,2. +!(hd
I"1\R8
R
但是我的想像中应该是这样的分布情况: q.7CPm+
c******* ^ytd~iK8
aa**bbbb $j/F7.S
dddddddd : Ej IV]e
U
DG _APf
不知为什么会c和a放在一起,组成8位长度。