Intel和微软同时出现的C语言面试题 1iTI8h&[@
#pragma pack(8) I8:A]
2Ub!wee
struct s1{ %RS8zN
short a; TcM;6h`
long b; I c 2R\}q
}; J-wF2*0r<
S)$iHBx{
struct s2{ ^\ocH|D
char c; \T]'d@Wyd
s1 d; yz7X7mAo
long long e; 6./3w&D;
}; FLzC kzJ:6
2j
<Y>Y
#pragma pack() +<1MY'>y
mW&hUPRx
问 &K.js
1.sizeof(s2) = ? Ufr,6IX
2.s2的s1中的a后面空了几个字节接着是b?
vle`#c.
M\rZr3
L.tW]43K
6A23H7
如果您知道答案请在讨论中写出,以下是部份网友的答案,供参考: K*[`s'Ip-
9 m`VIB
网友rwxybh(行云)的答案: o/~Rf1
内存布局是 Q^!x8oUF
1*** 11** 2Mo oqJp
1111 **** ]u<8jr
1111 1111 gql^Inx<
ziTE*rNJ
所以答案就是24和3 zz_(*0,Qcr
D(&XmC[\Y
下面是一个测试的程序,试一试就知道了,我用的是VC2005 >#Ue`)d`aY
sf5 F$
#pragma pack(8) A$o7<Hx
J[ 7Sf^r
struct s1{ !<#,M9
EA&
short a; // 2 BYtes fIwG9cR
long b; // 4 Bytes %("WoBPH`
}; H05xt$J
struct s2{ fuao*L]
char c; // 1 Byte >%1mx\y^
s1 d; // 8 Bytes /JbO $A
long long e; // 8 Bytes # ;3v4P
}; &X&msEM
// 1*** 11** M>g%wg7Ah
// 1111 **** w)7 s]Ld
// 1111 1111 GX0S9s
//
Xn=
- xKa-3
// 00 01 02 03 04 05 06 07 %D6HY^]ayw
// 00 01 02 03 04 05 06 07 WinwPn+9
// 00 01 02 03 04 05 06 07 n&\DJzW\#
// ={[9kR i
#pragma pack() 94Q?)0W$
HyGu3
int main(int argc, char* argv[]) y)uxj-G
{ fq4[/%6,O
s2 a; hywy(b3
char *p = (char *)&a; 2`P=ekF]
for(int i=0;i<24;++i) 8d1r#sILI
p = (char)(i%8); NnTAKd8
printf("%d\n",sizeof(a)); Gph:'3
*X
printf("c=0x%lx\n",a.c); RcpKv;= iB
printf("d.a=0x%x\n",a.d.a); ":W$$w<
printf("d.b=0x%x\n",a.d.b); LVe[N-K
printf("e=0x%llx\n",a.e); B0$ge"FK9
return 0; G7SmlFn?
} KvY1bMU!
结果: &e)V!o@wJV
24 T%O2=h\} E
c=0x0 U^
;H{S
d.a=0x504 #,CK;h9jy!
d.b=0x3020100 ;Z!x\{-L
e=0x706050403020100 'LMMo4o3
@XQItc<
>SHP,><H/
网友 redleaves (ID最吊的网友)的答案和分析: -=4{X
R3
HApjXv!U[
如果代码: rcUJOI
#pragma pack(8) Jk}Dj0o
struct S1{ <`")Zxf+
char a; F2!]T =
long b; FwwOp"[~t
}; R
"qt}4m
struct S2 { OJT%?P%@{
char c; Uu0
struct S1 d; ;D|g5$OE&
long long e; WwF2Ry^a
}; $0&<Jx
#pragma pack() XCj8QM.o
sizeof(S2)结果为24. <%"o-xZq7C
成员对齐有一个重要的条件,即每个成员分别对齐.即每个成员按自己的方式对齐. !EOYqD
也就是说上面虽然指定了按8字节对齐,但并不是所有的成员都是以8字节对齐.其对齐的规则是,每个成员按其类型的对齐参数(通常是这个类型的大小)和指定对齐参数(这里是8字节)中较小的一个对齐.并且结构的长度必须为所用过的所有对齐参数的整数倍,不够就补空字节. o2R&s@%0@B
c"oJcp
S1中,成员a是1字节默认按1字节对齐,指定对齐参数为8,这两个值中取1,a按1字节对齐;成员b是4个字节,默认是按4字节对齐,这时就按4字节对齐,所以sizeof(S1)应该为8; i;fU],aK!
S2中,c和S1中的a一样,按1字节对齐,而d 是个结构,它是8个字节,它按什么对齐呢?对于结构来说,它的默认对齐方式就是它的所有成员使用的对齐参数中最大的一个,S1的就是4.所以,成员d就是按4字节对齐.成员e是8个字节,它是默认按8字节对齐,和指定的一样,所以它对到8字节的边界上,这时,已经使用了12个字节了,所以又添加了4个字节的空,从第16个字节开始放置成员e.这时,长度为24,已经可以被8(成员e按8字节对齐)整除.这样,一共使用了24个字节. Aa}Nr5{O|
a b Dio)orc
S1的内存布局:11**,1111, a St:G*a"
c S1.a S1.b d d8J(~$tXQN
S2的内存布局:1***,11**,1111,****11111111 guk{3<d:Jy
FJ] ?45
这里有三点很重要: Q?V'3ZZF!
1.每个成员分别按自己的方式对齐,并能最小化长度 S!8q>d,%L
2.复杂类型(如结构)的默认对齐方式是它最长的成员的对齐方式,这样在成员是复杂类型时,可以最小化长度 dmPAPCm%y
3.对齐后的长度必须是成员中最大的对齐参数的整数倍,这样在处理数组时可以保证每一项都边界对齐 z<OfSS_]R
*:"p*qV*
cv"Bhql
网友xue23(xue23) 的答案和分析: 5
51p*
B2
}ws(:I^
有程序查一下各个变量的内存地址得知: qnJs,"sn
各个变量在内存中的位置为 >D_!d@Z
c***aa** !|~yf3
bbbb**** "Bl6)qw
dddddddd @umn[J#*
测试代码为: yX%NFXD
s2 ss; >!PCEw<i
cout << "ss.c = " << &ss << endl ; o#hFK'&~
cout << "ss.d.a = " <<&ss.d.a << endl; TJUYd9O4[
cout << "ss.d.b = " <<&(ss.d.b) < cout << "ss.d = " <<&ss.e << endl; FJ2~SKWT
print out 各个变量的内存地址不就可以看出来了吗。 n!h952"
Y2W{?<99
所以答案是24,2. C}]143a/Q
s&M#]8x;x
但是我的想像中应该是这样的分布情况: OjsMT]
c******* :'Tq5kE
aa**bbbb <~
?LU^
dddddddd LF ;gdF%@
!SThK8j$7
不知为什么会c和a放在一起,组成8位长度。