Intel和微软同时出现的C语言面试题 /pT=0=
#pragma pack(8) 'IwNTM
p>4-s, W
struct s1{ 1,% R;7J=g
short a; {GQ^fu;q
long b; INJEsz
}; cLLbZ=`
iv4H#rJ
struct s2{ `hQ5VJo
char c; 2.l:O2<
s1 d; 4rLL[??
long long e; !6*"(
}; S[J}UpV
_no*k?o*
#pragma pack() ?vbvBu{a
Z'.AA OG
问 ;IZwTXu !S
1.sizeof(s2) = ? c}2jmwq
2.s2的s1中的a后面空了几个字节接着是b? eQ]~dA8>
`~By)?cT_>
/w}u3|L$
t:'Mh9h7u
如果您知道答案请在讨论中写出,以下是部份网友的答案,供参考: wY[+ZT
NU5.o$
网友rwxybh(行云)的答案: OG>}M$Ora
内存布局是 ,,q10iF
1*** 11** 9-fLz?J
1111 **** Xg;}R:g '
1111 1111 }khV'6"'|
KV0]m^@x
所以答案就是24和3
2*^j
xD~5UER
下面是一个测试的程序,试一试就知道了,我用的是VC2005 DK:o]~n
q1d}{DU
#pragma pack(8) 9,:l8
-C(crn
struct s1{ <+?7H\b
short a; // 2 BYtes SC)g^E#
long b; // 4 Bytes 6[ j.@[t
}; ~E2KZm
struct s2{ lww!-(<ww
char c; // 1 Byte Ng~FEl
s1 d; // 8 Bytes H[U!%Z
long long e; // 8 Bytes 3 cK I
}; 0tT(W^ho g
// 1*** 11** :&V h?
// 1111 **** Dv5D~on{
// 1111 1111 #_^Lb]jkM
// 4R1<nZ"e~
vunHNHltW0
// 00 01 02 03 04 05 06 07 jtW!"TOY
// 00 01 02 03 04 05 06 07 (ROY?5
@c
// 00 01 02 03 04 05 06 07 Y[}>CYO
// #W4dkCd(pF
#pragma pack() H4&lb}
L.*M&Ry
int main(int argc, char* argv[]) gG(fQ
89U"
{ U`, 6 * MS
s2 a; "Q@ronP(~
char *p = (char *)&a; -g*4(w
for(int i=0;i<24;++i) 1mOh{:1u
p = (char)(i%8); Y)* #)f
printf("%d\n",sizeof(a)); EyJJ0
printf("c=0x%lx\n",a.c); (X\@t-8
printf("d.a=0x%x\n",a.d.a); JfLqtXF[&"
printf("d.b=0x%x\n",a.d.b); l5!|I:/*;
printf("e=0x%llx\n",a.e); eD?tLj
return 0; k@ RDvn
} 8]/bK5`
结果: _E@2ZnD2
24 hK L4cpK4
c=0x0 f!Y?S
d.a=0x504 5YE'L.
d.b=0x3020100 Jh,]r?Bd
e=0x706050403020100 R3gdLa.
Ezc?#<+7
e>+i>/Fn{h
网友 redleaves (ID最吊的网友)的答案和分析: 3no%E03p
`T@i. 'X
如果代码: u8&Z!p\
#pragma pack(8) lb4Pcdj
struct S1{ ~=M7 3U#
char a; SJb&m-
long b; . qO@Q =
}; 2_HNhW
struct S2 { n8~N$tDU
char c; #Z?A2r!1
struct S1 d; O_oPh] x)
long long e; "l3_=Gua
}; H1|?t+oP
#pragma pack() ype$ c
sizeof(S2)结果为24. `2("gUCm
成员对齐有一个重要的条件,即每个成员分别对齐.即每个成员按自己的方式对齐. PUT=C1,OFR
也就是说上面虽然指定了按8字节对齐,但并不是所有的成员都是以8字节对齐.其对齐的规则是,每个成员按其类型的对齐参数(通常是这个类型的大小)和指定对齐参数(这里是8字节)中较小的一个对齐.并且结构的长度必须为所用过的所有对齐参数的整数倍,不够就补空字节. #+ 0M2Sa
LM~[@_j
S1中,成员a是1字节默认按1字节对齐,指定对齐参数为8,这两个值中取1,a按1字节对齐;成员b是4个字节,默认是按4字节对齐,这时就按4字节对齐,所以sizeof(S1)应该为8; |W,&
Hl7
S2中,c和S1中的a一样,按1字节对齐,而d 是个结构,它是8个字节,它按什么对齐呢?对于结构来说,它的默认对齐方式就是它的所有成员使用的对齐参数中最大的一个,S1的就是4.所以,成员d就是按4字节对齐.成员e是8个字节,它是默认按8字节对齐,和指定的一样,所以它对到8字节的边界上,这时,已经使用了12个字节了,所以又添加了4个字节的空,从第16个字节开始放置成员e.这时,长度为24,已经可以被8(成员e按8字节对齐)整除.这样,一共使用了24个字节. >%}C^gu)
a b 6m*QX+
S1的内存布局:11**,1111, 3]}D`Qs6
c S1.a S1.b d ^a0um/+M}
S2的内存布局:1***,11**,1111,****11111111 N.,X<G.H
`i3NG1
v0
这里有三点很重要: q9KHmhUD
1.每个成员分别按自己的方式对齐,并能最小化长度 fInb[
2.复杂类型(如结构)的默认对齐方式是它最长的成员的对齐方式,这样在成员是复杂类型时,可以最小化长度 0L2 F[TN
3.对齐后的长度必须是成员中最大的对齐参数的整数倍,这样在处理数组时可以保证每一项都边界对齐 DR5\45v
dk[!V1x4\
yj 3cyLXw
网友xue23(xue23) 的答案和分析: 5d Eh7XL
T*Y~\~Jhu
有程序查一下各个变量的内存地址得知: [kVS
O
各个变量在内存中的位置为 a!6{:8Zi0
c***aa** deBY5|
bbbb**** wN_Vfb
dddddddd MU@UfB|;u
测试代码为: 44ek
IV+?
s2 ss; W9 GxXPA
cout << "ss.c = " << &ss << endl ; !Q2d(H>
cout << "ss.d.a = " <<&ss.d.a << endl; XRM_x:+]
cout << "ss.d.b = " <<&(ss.d.b) < cout << "ss.d = " <<&ss.e << endl; $v4.sl:x
print out 各个变量的内存地址不就可以看出来了吗。 JFcLv=U
>*~L28Fyn
所以答案是24,2. :3v}kLO7|
^S4d:-.3
但是我的想像中应该是这样的分布情况: b[r8e
c******* dI.WK@W'o
aa**bbbb jl4rbzse
dddddddd K
-nF lPm\
~ (|5/
p7t
不知为什么会c和a放在一起,组成8位长度。