Intel和微软同时出现的C语言面试题 %`\]Y']R
#pragma pack(8) %xg"Q|
?ApRJm:T
struct s1{ QlzQ]:dWC
short a; YdOUv|tZC
long b; P#tvm,
}; tHI*,
WcGXp$M
struct s2{ `BT*,6a
char c; l1-HO
s1 d; qi=3L
long long e; !Yh}H<w0
}; pCt}66k}
!wh=dQgMe
#pragma pack() 'DAltr<
9YC&&0 C@
问 )SiY(8y
1.sizeof(s2) = ? J+2R&3;_O
2.s2的s1中的a后面空了几个字节接着是b? UC!5
wVY
|~$7X
iHz[Zw^.s
hx!`F
如果您知道答案请在讨论中写出,以下是部份网友的答案,供参考: Nlt4)
YFx=b!/s
网友rwxybh(行云)的答案: TETsg5#
内存布局是 .hN3`>*V
1*** 11** p.Y$A
if.
1111 **** YvTA+yL
1111 1111 `"Dy%&U
gMZ&,n4
所以答案就是24和3 u%opY<h
L>nO:`>h
下面是一个测试的程序,试一试就知道了,我用的是VC2005 #v8Cy|I
79tJV
#pragma pack(8) BX$hAQ(6Q
`Cj,HI_/*
struct s1{ `^%GN8d}nm
short a; // 2 BYtes "6V_/u5M;=
long b; // 4 Bytes lG]GlgSs
}; WEC-<fN|Y\
struct s2{ >eo8
char c; // 1 Byte jOl 1_
s1 d; // 8 Bytes NgxO&Zp
long long e; // 8 Bytes I7Zq}Pxa
}; kPJ~X0Fr{t
// 1*** 11** iEhDaC[e(b
// 1111 **** Yq;&F0paK
// 1111 1111 @,vv\M0)p
// MZ^Ch
E& ]_U$
// 00 01 02 03 04 05 06 07 ^
wQcB
// 00 01 02 03 04 05 06 07 c~oe,9
// 00 01 02 03 04 05 06 07 I"V3+2e
// GTFl}t
#pragma pack() -s~p}CQ.
'%Dg{ zL
int main(int argc, char* argv[]) R6Pz#`n
{ bX{PSjD
s2 a; ^'Zh;WjI7
char *p = (char *)&a; SRk7gfP*q
for(int i=0;i<24;++i) r %xB8e9
p = (char)(i%8); YPQCOG
printf("%d\n",sizeof(a)); ~%G Ssm\J
printf("c=0x%lx\n",a.c);
* D3
printf("d.a=0x%x\n",a.d.a); WFdem/\kX
printf("d.b=0x%x\n",a.d.b); Prt#L8
printf("e=0x%llx\n",a.e); JWSq"N
return 0; gT7I9 (x!W
} $y4M#yv
结果: :+A;TV
24 9jjL9f_3
c=0x0 nK:`e9ES
d.a=0x504 g{&PrE'e9
d.b=0x3020100 \]GGVI;u
e=0x706050403020100 "b;k.Fx
bgXc_>T6_y
2 ^ kn5
网友 redleaves (ID最吊的网友)的答案和分析: s.ey!ew
73#9NZR
如果代码: /
GZV_H%v
#pragma pack(8) sp,(&Y]US
struct S1{ ?(M\:`G'
char a; [M2Dy{dh
long b; Ua!Odju*w
}; D2-O7e
struct S2 { <v-92?
char c; "lb\c
struct S1 d; 6!o/~I#
long long e; 2X +7bM
}; $pJ3xp&
#pragma pack() lZ+/\s,]|
sizeof(S2)结果为24. _4S7wOq5
成员对齐有一个重要的条件,即每个成员分别对齐.即每个成员按自己的方式对齐. BC&^]M
也就是说上面虽然指定了按8字节对齐,但并不是所有的成员都是以8字节对齐.其对齐的规则是,每个成员按其类型的对齐参数(通常是这个类型的大小)和指定对齐参数(这里是8字节)中较小的一个对齐.并且结构的长度必须为所用过的所有对齐参数的整数倍,不够就补空字节. ix+x3OCip
<m9JXO:5
S1中,成员a是1字节默认按1字节对齐,指定对齐参数为8,这两个值中取1,a按1字节对齐;成员b是4个字节,默认是按4字节对齐,这时就按4字节对齐,所以sizeof(S1)应该为8; M%77u=m
S2中,c和S1中的a一样,按1字节对齐,而d 是个结构,它是8个字节,它按什么对齐呢?对于结构来说,它的默认对齐方式就是它的所有成员使用的对齐参数中最大的一个,S1的就是4.所以,成员d就是按4字节对齐.成员e是8个字节,它是默认按8字节对齐,和指定的一样,所以它对到8字节的边界上,这时,已经使用了12个字节了,所以又添加了4个字节的空,从第16个字节开始放置成员e.这时,长度为24,已经可以被8(成员e按8字节对齐)整除.这样,一共使用了24个字节. ~M(pCSJ[
a b a\|X^%2g
S1的内存布局:11**,1111, <#!8?o&i
c S1.a S1.b d ,P1G?,y
S2的内存布局:1***,11**,1111,****11111111 kfIbgya
&A#90xzF
这里有三点很重要: _4A&%>
1.每个成员分别按自己的方式对齐,并能最小化长度 ]n/jJ_[
2.复杂类型(如结构)的默认对齐方式是它最长的成员的对齐方式,这样在成员是复杂类型时,可以最小化长度 r6/<&1[
3.对齐后的长度必须是成员中最大的对齐参数的整数倍,这样在处理数组时可以保证每一项都边界对齐 s
UvKA0
,7/\&X<`B
4v i B=>
网友xue23(xue23) 的答案和分析: ol1AD: Ho
]dQZ8yVK
有程序查一下各个变量的内存地址得知: |Yg}WHm
各个变量在内存中的位置为 |O'Hh7
c***aa** /Ir 7
DZK
bbbb**** 7YSuB9{M
dddddddd @#J H=-06
测试代码为: <4S F~i
s2 ss; ~n)]dFy
cout << "ss.c = " << &ss << endl ; eq7C]i
rH
cout << "ss.d.a = " <<&ss.d.a << endl; NdaM9a#TZ
cout << "ss.d.b = " <<&(ss.d.b) < cout << "ss.d = " <<&ss.e << endl; m}sh I8S
print out 各个变量的内存地址不就可以看出来了吗。 +._f.BRmX.
$::51#^Wg
所以答案是24,2. y0lL Fe~
Z7ZWf'o
但是我的想像中应该是这样的分布情况: -U&098}<K
c******* qrOB_Nz
aa**bbbb ([E#zrz%
dddddddd 4_Tb)?L+:
P[r}(@0rJ
不知为什么会c和a放在一起,组成8位长度。