Intel和微软同时出现的C语言面试题 '=|2, H]
#pragma pack(8) R)>/P{A-P
o80"ZU|=
struct s1{ MYQZqlV
short a; %/l9$>{
long b; /Iwnl
}; ()< E?D=
RC_w 1:h
struct s2{ OYw~I.Rq
char c; s
"KPTV
s1 d; %M=[h2SN
long long e; _l?InNv
}; (!-gX"<b
-WDU~VSU
#pragma pack() %SKp<>;9
Uu~7+oaQ
问 8p4J7 -
1.sizeof(s2) = ? <a)B5B>
2.s2的s1中的a后面空了几个字节接着是b? "}_b,5lkGK
X^!n'$^u
{1RI!#[\
r(ej=aR
如果您知道答案请在讨论中写出,以下是部份网友的答案,供参考: )E--E+j
)ZxDfRjL
网友rwxybh(行云)的答案: Xb0$BAP
内存布局是 72hN%l
1*** 11** hE|Z~5\Y,>
1111 **** p.{M s n
1111 1111 {H]xA 3[]
h28")c.pH=
所以答案就是24和3 fj2pD Cic
/}G+PUk7
下面是一个测试的程序,试一试就知道了,我用的是VC2005 "7v/-
#6< X
#pragma pack(8) V$y6=Q<c
AJk0jh\.j%
struct s1{ ao4"=My*G
short a; // 2 BYtes >s
4"2X
long b; // 4 Bytes )tH.P:
1~,
}; J~=bW\^I
struct s2{ l@ +lUx8
char c; // 1 Byte %4F
Q~
s1 d; // 8 Bytes 8(yZX4OH>
long long e; // 8 Bytes hu?Q,[+o
}; g"k1O
// 1*** 11** 8>T#sO?+
// 1111 **** Y ^s_v_s
// 1111 1111 |eN#9Bm
// A1b</2
qJjXN+/D
// 00 01 02 03 04 05 06 07 G?:{9. (
// 00 01 02 03 04 05 06 07 Yt]tRqrh;T
// 00 01 02 03 04 05 06 07 W62 $ HI
// 8nt3Sm
#pragma pack() {M`yYeo
7Hghn"ol
int main(int argc, char* argv[]) "gm[q."n<
{ ~0}gRpMW
s2 a; HGuU6@~hu
char *p = (char *)&a; (HNxo{t
for(int i=0;i<24;++i) M^q< qS>d
p = (char)(i%8); ~UrKyA
printf("%d\n",sizeof(a)); 4(
Q_J4}P
printf("c=0x%lx\n",a.c); L-&N*
printf("d.a=0x%x\n",a.d.a); =mVWfFL
printf("d.b=0x%x\n",a.d.b); 8*nv+
printf("e=0x%llx\n",a.e); w_c)iJ
return 0; y^PQgzm]
} ,g69 ?w
结果: r[doN{%
24 n$2IaE;v
c=0x0 /_WAF90R?
d.a=0x504 eUBf-xA
d.b=0x3020100 %bu$t,
e=0x706050403020100 C%2BDj
{e'P*j
~lBb%M
网友 redleaves (ID最吊的网友)的答案和分析: 6Zr_W#SE
g=Gd|
如果代码: l ga%U~
#pragma pack(8) OyI?P_0u
struct S1{ ` ,lm:x+(0
char a; o#"U8N%r
long b; KCBA`N8
}; q=I8W}Zi
struct S2 { l#%qF Db
char c; #'DrgZ)W
struct S1 d; a0wSXd
long long e; #$5"&SM
}; ;(&$Iw9X
#pragma pack() X8}m
%
sizeof(S2)结果为24. /KU9sIE;
成员对齐有一个重要的条件,即每个成员分别对齐.即每个成员按自己的方式对齐. *~h@K Qm7
也就是说上面虽然指定了按8字节对齐,但并不是所有的成员都是以8字节对齐.其对齐的规则是,每个成员按其类型的对齐参数(通常是这个类型的大小)和指定对齐参数(这里是8字节)中较小的一个对齐.并且结构的长度必须为所用过的所有对齐参数的整数倍,不够就补空字节. _f5>r (1Q
7aF'E1e'3
S1中,成员a是1字节默认按1字节对齐,指定对齐参数为8,这两个值中取1,a按1字节对齐;成员b是4个字节,默认是按4字节对齐,这时就按4字节对齐,所以sizeof(S1)应该为8; U yb -feG
S2中,c和S1中的a一样,按1字节对齐,而d 是个结构,它是8个字节,它按什么对齐呢?对于结构来说,它的默认对齐方式就是它的所有成员使用的对齐参数中最大的一个,S1的就是4.所以,成员d就是按4字节对齐.成员e是8个字节,它是默认按8字节对齐,和指定的一样,所以它对到8字节的边界上,这时,已经使用了12个字节了,所以又添加了4个字节的空,从第16个字节开始放置成员e.这时,长度为24,已经可以被8(成员e按8字节对齐)整除.这样,一共使用了24个字节. ,/fB~On-
a b QN4{xf:}S
S1的内存布局:11**,1111, BlLK6"gJT
c S1.a S1.b d /9SEW!E
S2的内存布局:1***,11**,1111,****11111111 Y ~TR`y
`w&A;fR!H
这里有三点很重要: B$ =oU
1.每个成员分别按自己的方式对齐,并能最小化长度 /)%$xi
2.复杂类型(如结构)的默认对齐方式是它最长的成员的对齐方式,这样在成员是复杂类型时,可以最小化长度 ]_"c_QG
3.对齐后的长度必须是成员中最大的对齐参数的整数倍,这样在处理数组时可以保证每一项都边界对齐 X!aC6gujOH
@AB}r1E2
_i3?;Fds
网友xue23(xue23) 的答案和分析: M]Kxg;
:P2{^0$
有程序查一下各个变量的内存地址得知: :VkuK@Th`
各个变量在内存中的位置为 c
-sc*.&
c***aa** 8+*
1s7{
bbbb**** 1bz%O2U-(
dddddddd ?\Bm>p%+
测试代码为: p*NKM}
]I
s2 ss; c-`'`L^J
cout << "ss.c = " << &ss << endl ; }1xD*[W
cout << "ss.d.a = " <<&ss.d.a << endl; Cs!z3QU
cout << "ss.d.b = " <<&(ss.d.b) < cout << "ss.d = " <<&ss.e << endl; 009[`Z
print out 各个变量的内存地址不就可以看出来了吗。 XRl!~Y|
9QXBz=Fnf
所以答案是24,2. 0hNgr'
T'ko =k
但是我的想像中应该是这样的分布情况: /` ;rlH*
c******* ;L*Ku'6Mt
aa**bbbb ]>9[}'u
dddddddd .4[\%r\i
ngt?9i;N
不知为什么会c和a放在一起,组成8位长度。