Intel和微软同时出现的C语言面试题 J@/kIrx
#pragma pack(8) pE3?"YO
Ij7p'a
struct s1{ rP'me2
B
short a; =ke2;}X
long b; =1@u
}; 2,y|EpG#
'NbHa!
struct s2{ G~]Uk*M
q
char c; T )&A2q
s1 d; =bAx,,D#
long long e; +X\FBvP&
}; c^5~QGuQ
V%t.l
#pragma pack() DcS+_>a\{l
{Ea
b
j
问 ]]HNd7Vh
1.sizeof(s2) = ? 5p,RI&nlN
2.s2的s1中的a后面空了几个字节接着是b? W Tcw4
;_XFo&@
K,tQ!kk
;gD})@
如果您知道答案请在讨论中写出,以下是部份网友的答案,供参考: %6t:(z
av(6wht8
网友rwxybh(行云)的答案: Ml`:UrU
内存布局是 e_^26^{q
1*** 11** cQjv$$&6[
1111 **** mwO6g~@`
1111 1111 QDZWX`qw{
m%0p\Y-/
所以答案就是24和3 9v#CE!
ynp 8rf
下面是一个测试的程序,试一试就知道了,我用的是VC2005 YByLoM*
+l42Awl>K
#pragma pack(8) .S EdY:
V_)-#=J
struct s1{ ),_@WW;k
short a; // 2 BYtes uIY#e<)}G
long b; // 4 Bytes n5|fHk^s
}; ]|#+zx|/D
struct s2{ "BAK !N$9
char c; // 1 Byte g9OY<w5s]
s1 d; // 8 Bytes BqEI(c6
long long e; // 8 Bytes r[e##M
}; (xycJ`N
// 1*** 11** ?C]vS_jAh
// 1111 **** 6dHOf,zjm
// 1111 1111 z,RhYm
// k``_EiV4t
pt?bWyKG
// 00 01 02 03 04 05 06 07 >k|5Okq g
// 00 01 02 03 04 05 06 07 ]43/`FX
// 00 01 02 03 04 05 06 07 L]7=?vN=8
// />C^WQI^
#pragma pack() +8T?{K
rDtY[
int main(int argc, char* argv[]) K&u_R
{ cUk7i`M;6
s2 a; .C%<P"=J4h
char *p = (char *)&a; D#aDv0b
for(int i=0;i<24;++i) -au^;CM
p = (char)(i%8); Nd4f^Y
printf("%d\n",sizeof(a)); ]dVGUG8
printf("c=0x%lx\n",a.c); 4>YR{
printf("d.a=0x%x\n",a.d.a); cs48*+m
printf("d.b=0x%x\n",a.d.b); <(#(hDwy
printf("e=0x%llx\n",a.e); 0J*??g-n
return 0; *YI98
} yHYsZ,GE
结果: `K"L /I9
24 v4<nI;Ux
c=0x0 \Dm";Ay>
d.a=0x504 @ 6\I~s(
d.b=0x3020100 Q) #B0NA;T
e=0x706050403020100 SZ7:u895E
?9vuuIE
m<G,[Yc
网友 redleaves (ID最吊的网友)的答案和分析: l03B=$
2F[ q).
如果代码: S
E<FL/x1#
#pragma pack(8) ]Ee?6]bN
struct S1{
y`iBFC;_
char a; q~Hn-5H4Q
long b; gE'sOT9v
}; ,O5NLg-
struct S2 { ~i= _J3'
char c; I@\lN&HC
struct S1 d; B^=-Z8
long long e; pp?D7S
}; .N;=\C*
#pragma pack() ;._
l0Jw
sizeof(S2)结果为24. cdH>n)
成员对齐有一个重要的条件,即每个成员分别对齐.即每个成员按自己的方式对齐. E,Z$pKL?
也就是说上面虽然指定了按8字节对齐,但并不是所有的成员都是以8字节对齐.其对齐的规则是,每个成员按其类型的对齐参数(通常是这个类型的大小)和指定对齐参数(这里是8字节)中较小的一个对齐.并且结构的长度必须为所用过的所有对齐参数的整数倍,不够就补空字节. XTs8s12
_~m5^Q&
S1中,成员a是1字节默认按1字节对齐,指定对齐参数为8,这两个值中取1,a按1字节对齐;成员b是4个字节,默认是按4字节对齐,这时就按4字节对齐,所以sizeof(S1)应该为8;
Q>qUk@
S2中,c和S1中的a一样,按1字节对齐,而d 是个结构,它是8个字节,它按什么对齐呢?对于结构来说,它的默认对齐方式就是它的所有成员使用的对齐参数中最大的一个,S1的就是4.所以,成员d就是按4字节对齐.成员e是8个字节,它是默认按8字节对齐,和指定的一样,所以它对到8字节的边界上,这时,已经使用了12个字节了,所以又添加了4个字节的空,从第16个字节开始放置成员e.这时,长度为24,已经可以被8(成员e按8字节对齐)整除.这样,一共使用了24个字节. t|?ez4/{z
a b j a[Et/r
S1的内存布局:11**,1111, @/~omg}R
c S1.a S1.b d r wL`Czs
S2的内存布局:1***,11**,1111,****11111111 HdI8f!X'TG
PN%zIkbo
这里有三点很重要: ^S<Y>Nm]
1.每个成员分别按自己的方式对齐,并能最小化长度 ho{*Cjv
2.复杂类型(如结构)的默认对齐方式是它最长的成员的对齐方式,这样在成员是复杂类型时,可以最小化长度 DPY}?dC
3.对齐后的长度必须是成员中最大的对齐参数的整数倍,这样在处理数组时可以保证每一项都边界对齐 YRk(u7:0
D>r&}6<
&A/]pi-\
网友xue23(xue23) 的答案和分析: 0q
>~rTqtKd
有程序查一下各个变量的内存地址得知: O^PKn_OJ
各个变量在内存中的位置为 G&SB-
c***aa** 3d8L6GJ
bbbb**** [Y/}
^
dddddddd OF>mF~
测试代码为: 2>9C-VL2
s2 ss; 1.JK33
cout << "ss.c = " << &ss << endl ; ZgJQ?S$D
cout << "ss.d.a = " <<&ss.d.a << endl; L&8~f]
cout << "ss.d.b = " <<&(ss.d.b) < cout << "ss.d = " <<&ss.e << endl; jwe *(k]z
print out 各个变量的内存地址不就可以看出来了吗。 lgAoJ[
5<k"K^0QS
所以答案是24,2. ~\SGb_2
OnziG+ak
但是我的想像中应该是这样的分布情况: $p8xEcQdU#
c******* T~?Ff|qFC
aa**bbbb ' {OgN}'{
dddddddd >{]%F*p4
G5_=H,Vmd
不知为什么会c和a放在一起,组成8位长度。