Intel和微软同时出现的C语言面试题 >dpbCPJ9[
#pragma pack(8) yjEI/9_
$ph0ag+
struct s1{ [kbC'Eh*
short a; -IBO5;2_
long b; gbm0H-A:*
}; }B y)y;~
3{N\A5~
struct s2{ [E>R.Oe
char c; fO].e"}
s1 d; 8>UKIdp
long long e; Fr-[UZ~V
}; :GQUM 6
M
h`CP
#pragma pack() k$C"xg2
Dp*:Q){>E
问 u]HS(B,ht
1.sizeof(s2) = ? mZwi7s&u
2.s2的s1中的a后面空了几个字节接着是b? tbq|,"
Ko#4z%Yq
z!fdx|PUX
4s9c#nVlu
如果您知道答案请在讨论中写出,以下是部份网友的答案,供参考: YgCc|W3{
cDCJ]iDs
网友rwxybh(行云)的答案: d,W/M(S
内存布局是 ,I]7g4~
1*** 11** Oqpp=7
1111 **** vXephR'
1111 1111 W1vCN31
Fse['O~
所以答案就是24和3 eY
T8$
9"~9hOEct
下面是一个测试的程序,试一试就知道了,我用的是VC2005 (]2<?x*
)8;{nqoC
#pragma pack(8) j"5Pe
xw ?CMA
struct s1{ (@ "=F6P
short a; // 2 BYtes v"rl5x
long b; // 4 Bytes vF"c
}; Vu}806kB
struct s2{ 7Yuk
char c; // 1 Byte @7-=zt+f
s1 d; // 8 Bytes [4p=X=B
long long e; // 8 Bytes (Akd8}nf~
}; `)6>nPr7P
// 1*** 11** O@s{uZ|A6
// 1111 **** h1#S+k
// 1111 1111 5.wiTy
// lr WLN
e#.\^
// 00 01 02 03 04 05 06 07 E#8_hT]5
// 00 01 02 03 04 05 06 07 gI)u}JX
// 00 01 02 03 04 05 06 07 R2l[Q){!
// rJDnuR
#pragma pack() 2}w#3K
)R~aA#<>
int main(int argc, char* argv[]) (^LS']ybc
{ gQy~kctQ#
s2 a; be7L="vZw
char *p = (char *)&a; E/ijvuO
for(int i=0;i<24;++i) \<ZLoy_
p = (char)(i%8); S_2"7
printf("%d\n",sizeof(a)); (#$$nQj
printf("c=0x%lx\n",a.c); >8|+%pK8<
printf("d.a=0x%x\n",a.d.a); `fz,Lh*v
printf("d.b=0x%x\n",a.d.b); =`-|&
printf("e=0x%llx\n",a.e); :j@8L.<U
return 0; (3VGaUlx
} ),=@q+{E{
结果: V5AW&kfd
24 3[r";Wt#
c=0x0 Z'Q*L?E8M
d.a=0x504 {b1UX9y
d.b=0x3020100 c`
,
2h#
e=0x706050403020100 9x?B5Ap[
ZHCr2^w6
P/MM
UmO
网友 redleaves (ID最吊的网友)的答案和分析: cx{T
'1
7S<UFj
如果代码: X D) 8?
#pragma pack(8) Ra[>P _
struct S1{ dx@QWTNE
char a; /THnfy\
long b; rgqQxe=
}; Iq^if>
struct S2 { Hd%!Nt\u
char c; 78d_io}w
struct S1 d; NG" yPn
long long e; Bd5+/G=m
}; $w)~xE5;
#pragma pack() ;#&fgj
sizeof(S2)结果为24. W`rMtzL5
成员对齐有一个重要的条件,即每个成员分别对齐.即每个成员按自己的方式对齐. *"cD.)]#2
也就是说上面虽然指定了按8字节对齐,但并不是所有的成员都是以8字节对齐.其对齐的规则是,每个成员按其类型的对齐参数(通常是这个类型的大小)和指定对齐参数(这里是8字节)中较小的一个对齐.并且结构的长度必须为所用过的所有对齐参数的整数倍,不够就补空字节. XK qK<!F
=1Z;Ma<;
S1中,成员a是1字节默认按1字节对齐,指定对齐参数为8,这两个值中取1,a按1字节对齐;成员b是4个字节,默认是按4字节对齐,这时就按4字节对齐,所以sizeof(S1)应该为8; WhFS2Jl0
S2中,c和S1中的a一样,按1字节对齐,而d 是个结构,它是8个字节,它按什么对齐呢?对于结构来说,它的默认对齐方式就是它的所有成员使用的对齐参数中最大的一个,S1的就是4.所以,成员d就是按4字节对齐.成员e是8个字节,它是默认按8字节对齐,和指定的一样,所以它对到8字节的边界上,这时,已经使用了12个字节了,所以又添加了4个字节的空,从第16个字节开始放置成员e.这时,长度为24,已经可以被8(成员e按8字节对齐)整除.这样,一共使用了24个字节. rA1qSG~c
a b *P!s{i
S1的内存布局:11**,1111, K"\MU
c S1.a S1.b d 6):Xzx,
S2的内存布局:1***,11**,1111,****11111111 l}rS{+:wK
blahi]{Y9
这里有三点很重要: Km!nM$=k
1.每个成员分别按自己的方式对齐,并能最小化长度 R*9NR,C
2.复杂类型(如结构)的默认对齐方式是它最长的成员的对齐方式,这样在成员是复杂类型时,可以最小化长度 "'a* [%
3.对齐后的长度必须是成员中最大的对齐参数的整数倍,这样在处理数组时可以保证每一项都边界对齐 ]\Xc9N8w
Gf0,RH+
02\JzBU
网友xue23(xue23) 的答案和分析: m!O;>D
Yp1bH+/u
有程序查一下各个变量的内存地址得知: }HRK?.Vj:
各个变量在内存中的位置为 nWJ:=JQ i"
c***aa** Tf x :"u
bbbb**** 5f^>b\8+ |
dddddddd JYm7@gx
测试代码为: gsPl _
s2 ss; UXH"si:
cout << "ss.c = " << &ss << endl ; I%"'*7U
cout << "ss.d.a = " <<&ss.d.a << endl; eEl.. y
cout << "ss.d.b = " <<&(ss.d.b) < cout << "ss.d = " <<&ss.e << endl; T5|c$doQ
print out 各个变量的内存地址不就可以看出来了吗。 |cDszoT
/
0q,pi qjO
所以答案是24,2. M T6/2d
P`jL]x
但是我的想像中应该是这样的分布情况: Wto;bd
c******* C5@V/vA
aa**bbbb (K :]7
dddddddd l-Nly>~
ECcZz.
不知为什么会c和a放在一起,组成8位长度。