Intel和微软同时出现的C语言面试题 /oL8;:m
#pragma pack(8) B+"g2Y
10O$'`
struct s1{ p3yU:q#A
short a; 9$RIH\*
long b; $iPP|Rw
}; !h: Q
eW50s`bKY
struct s2{ _kN*e:t
char c; W&C-/O,m
s1 d; Gx'TkU=
long long e; Z 0*%Rq
}; 3ZojE ux`
<kbyZXV@K
#pragma pack() Cv^`&\[SW+
;`UecLb#
问 Yb:pAzw6
1.sizeof(s2) = ? :(p)1=I
2.s2的s1中的a后面空了几个字节接着是b? r}W2 Ak\
8\Hr5FqB(
wC`
R>)
8omC%a}9m
如果您知道答案请在讨论中写出,以下是部份网友的答案,供参考: 2"&)W dm
zOB=aG?/
网友rwxybh(行云)的答案: A'-_TFwW
内存布局是 c\.P/~
1*** 11** ,.v7FM^gO
1111 **** 7bF*AYM
1111 1111 Y7SacRO
CdZ BG
所以答案就是24和3 XUmR{A
=k{`oO~:9+
下面是一个测试的程序,试一试就知道了,我用的是VC2005 GwLFL.Ke
]KuMz p!
#pragma pack(8) o2uj =Gnx
s>%Pd7:
struct s1{ o6L9UdT
short a; // 2 BYtes |d}MxS`^
long b; // 4 Bytes qf8[!5GM
}; AK-}V4C/A
struct s2{ KnzsHli,~k
char c; // 1 Byte ^gYD*K!*
s1 d; // 8 Bytes tju|UhP3
long long e; // 8 Bytes ,pt%)
c
}; ,Em$ !n
// 1*** 11** thW<
// 1111 **** d,cN(
// 1111 1111 n$["z
w
// A6"Hk0Hf
Wa'sZ#
// 00 01 02 03 04 05 06 07 H0*,8i5I
// 00 01 02 03 04 05 06 07 c&'JmKV>&
// 00 01 02 03 04 05 06 07 ${hz e<g
// <{J5W6
#pragma pack() rg QEUDEQ
GWP dv
int main(int argc, char* argv[]) LE=k
{ z/]q)`G
s2 a; vO@s$qi
char *p = (char *)&a; lU2c_4
for(int i=0;i<24;++i) Pz"`MB<'Ik
p = (char)(i%8); !Pj/7JC0
printf("%d\n",sizeof(a)); =
+Xc4a
printf("c=0x%lx\n",a.c); pwX C
printf("d.a=0x%x\n",a.d.a); {]}s#vvy
printf("d.b=0x%x\n",a.d.b); b.yh8|&
printf("e=0x%llx\n",a.e); Mi7y&~,
return 0; qE7R4>5xjO
} *r,b=8|
结果: &h~aChJ
24 [=TCEU{"~
c=0x0 p@Q5b}xCG_
d.a=0x504 `,>wC+}
d.b=0x3020100 >_ \<E!j
e=0x706050403020100 qr(`&hB-L
9w4sSj`
FG-L0X
网友 redleaves (ID最吊的网友)的答案和分析: I!: z,t<
HAB#pd9
如果代码: =U-r*sGLN
#pragma pack(8) %i0\1hhV<
struct S1{ T1Ta?b
char a; Rm>^tu
-
long b; g /+oZU
}; &jQ?v@|1c
struct S2 { 6XV<?
9q
char c; 2j&@p>
struct S1 d; !.X.tc
long long e; `$RA< 3
}; 9s$U%F6}
#pragma pack() 7v"lNP-?jU
sizeof(S2)结果为24. ":;@Hnb/
成员对齐有一个重要的条件,即每个成员分别对齐.即每个成员按自己的方式对齐. *,WP,-0
也就是说上面虽然指定了按8字节对齐,但并不是所有的成员都是以8字节对齐.其对齐的规则是,每个成员按其类型的对齐参数(通常是这个类型的大小)和指定对齐参数(这里是8字节)中较小的一个对齐.并且结构的长度必须为所用过的所有对齐参数的整数倍,不够就补空字节. (!K_Fy@
+V(5w`qx
S1中,成员a是1字节默认按1字节对齐,指定对齐参数为8,这两个值中取1,a按1字节对齐;成员b是4个字节,默认是按4字节对齐,这时就按4字节对齐,所以sizeof(S1)应该为8; LLAa1Wq
S2中,c和S1中的a一样,按1字节对齐,而d 是个结构,它是8个字节,它按什么对齐呢?对于结构来说,它的默认对齐方式就是它的所有成员使用的对齐参数中最大的一个,S1的就是4.所以,成员d就是按4字节对齐.成员e是8个字节,它是默认按8字节对齐,和指定的一样,所以它对到8字节的边界上,这时,已经使用了12个字节了,所以又添加了4个字节的空,从第16个字节开始放置成员e.这时,长度为24,已经可以被8(成员e按8字节对齐)整除.这样,一共使用了24个字节. ?pGkk=,KB
a b D&:yMp(
S1的内存布局:11**,1111, (M-ZQ
-
c S1.a S1.b d NYB[Zyp
S2的内存布局:1***,11**,1111,****11111111 {U11^w1"3
P&A|PY,P
这里有三点很重要: kJK,6mN
1.每个成员分别按自己的方式对齐,并能最小化长度 `k{& /]
2.复杂类型(如结构)的默认对齐方式是它最长的成员的对齐方式,这样在成员是复杂类型时,可以最小化长度 \}]iS C.2
3.对齐后的长度必须是成员中最大的对齐参数的整数倍,这样在处理数组时可以保证每一项都边界对齐 ]o/|na*
yubSj*
h5zVGr
网友xue23(xue23) 的答案和分析: (Ye>Cp+]
j
-O2aL
有程序查一下各个变量的内存地址得知: }-<zWI{p
各个变量在内存中的位置为 OyG"1F
c***aa** B5am1y{P#
bbbb**** Vd9@Dy
dddddddd <eN R8(P
测试代码为: 0Fr1Ku!
s2 ss; [bQj,PZ&
cout << "ss.c = " << &ss << endl ; b3qc_
cout << "ss.d.a = " <<&ss.d.a << endl; rnm03 '{
cout << "ss.d.b = " <<&(ss.d.b) < cout << "ss.d = " <<&ss.e << endl; $ItF])Bj5N
print out 各个变量的内存地址不就可以看出来了吗。 adEJk
q 2?X"!
所以答案是24,2. 6vzk\n
\>/M .2
但是我的想像中应该是这样的分布情况: HRa@
c******* T5lQIr@a
aa**bbbb xycH~ ?
dddddddd Z+:D)L
[Gr*,nVvB
不知为什么会c和a放在一起,组成8位长度。