Intel和微软同时出现的C语言面试题 (0^ZZe`#j
#pragma pack(8) /^=8?wK
R 0YWe
struct s1{ K#xL-
short a; /-Z}=
long b; e$o]f"(
}; `j!XWh*$
% !Ih=DZ
struct s2{ w[OUGn'
char c; @z>DJ>htN
s1 d; )8;At'q}
long long e; ~9n30j%]s
}; N."x@mV
z8cefD9F
#pragma pack() 40} 7O<9*
B0D
问 jGe%'AN\
1.sizeof(s2) = ? ]D[\l$(
2.s2的s1中的a后面空了几个字节接着是b? T}59m;I
"w3%BbI x
]EqwDw4
ji.T7wn1u
如果您知道答案请在讨论中写出,以下是部份网友的答案,供参考: ;2[),k
o2!wz8
网友rwxybh(行云)的答案: 6o4Y]C2W{1
内存布局是 BJKv9x1jK
1*** 11** U<<XeSp
1111 **** 8&3KVd`
1111 1111 w>\_d
WaSZw0U}y
所以答案就是24和3 3!vnSX(iv
"v/Yw'!
)
下面是一个测试的程序,试一试就知道了,我用的是VC2005 P|t2%:_
jc HyRR1R
#pragma pack(8) lcK4 Uq\q
;.=]Ar}
struct s1{ n0g8B
short a; // 2 BYtes gFl@A}
long b; // 4 Bytes @D>qo=KPM
}; Z{x)v5yh2V
struct s2{ m"!Q5[
char c; // 1 Byte b>Ea_3T/
s1 d; // 8 Bytes OAf}\
long long e; // 8 Bytes ~I;|ipK4m
}; |G_, 1$
// 1*** 11** 7[I +1
// 1111 **** _{$<s[S
// 1111 1111 zwk&3
// O_L>We@3E
v2k@yxt(
// 00 01 02 03 04 05 06 07 tXcZl!3x
// 00 01 02 03 04 05 06 07 }m&\I
// 00 01 02 03 04 05 06 07 S_?sJwM
// wHh6y? g\
#pragma pack() n'[>h0
6Ta+f3V
int main(int argc, char* argv[]) (__$YQ-
{ {vdY(
s2 a; \&47u1B
char *p = (char *)&a; $gZiW 8
for(int i=0;i<24;++i) =\G`g#
p = (char)(i%8); ~RLWr.pK
printf("%d\n",sizeof(a)); @0(%ayi2Y
printf("c=0x%lx\n",a.c); y?U@F/^}N
printf("d.a=0x%x\n",a.d.a); FC
WF$'cO
printf("d.b=0x%x\n",a.d.b); dh9@3. t
printf("e=0x%llx\n",a.e); udmLHc
return 0; n|Ts:>`V
} %xr'96d
结果: aM1WC 'c&)
24 ;`c:Law4
c=0x0 E#Ue9J
d.a=0x504 1|-C(UW>
d.b=0x3020100 -c1-vGW/
e=0x706050403020100 qGR1$\]
m*HUT V
@
N'P?i
网友 redleaves (ID最吊的网友)的答案和分析: a6ryyt 5
T,a{mi.hNR
如果代码: 0S; Ipg
#pragma pack(8) t4d/%b~{:U
struct S1{ eYoc(bG(+
char a; 0vDvp`ie#4
long b; roAHkI
}; 2B6u)
95
struct S2 { *^7^g!=z2
char c; %
q!i
struct S1 d; ]e5aHpgR=
long long e; ~H?v L c;>
}; #P z'-lo
#pragma pack() CE
sizeof(S2)结果为24. `|"o\Bg<
成员对齐有一个重要的条件,即每个成员分别对齐.即每个成员按自己的方式对齐. .Wp(@l'Hd
也就是说上面虽然指定了按8字节对齐,但并不是所有的成员都是以8字节对齐.其对齐的规则是,每个成员按其类型的对齐参数(通常是这个类型的大小)和指定对齐参数(这里是8字节)中较小的一个对齐.并且结构的长度必须为所用过的所有对齐参数的整数倍,不够就补空字节. s nxwe
^-s7>F`jx
S1中,成员a是1字节默认按1字节对齐,指定对齐参数为8,这两个值中取1,a按1字节对齐;成员b是4个字节,默认是按4字节对齐,这时就按4字节对齐,所以sizeof(S1)应该为8; AVU'rsXA
S2中,c和S1中的a一样,按1字节对齐,而d 是个结构,它是8个字节,它按什么对齐呢?对于结构来说,它的默认对齐方式就是它的所有成员使用的对齐参数中最大的一个,S1的就是4.所以,成员d就是按4字节对齐.成员e是8个字节,它是默认按8字节对齐,和指定的一样,所以它对到8字节的边界上,这时,已经使用了12个字节了,所以又添加了4个字节的空,从第16个字节开始放置成员e.这时,长度为24,已经可以被8(成员e按8字节对齐)整除.这样,一共使用了24个字节. rk&oKd_&i
a b pX>wMc+
S1的内存布局:11**,1111, Ekrpg^3qp"
c S1.a S1.b d W^ask[46R
S2的内存布局:1***,11**,1111,****11111111 knHrMD;
XAF]B,h=
这里有三点很重要: H&F2[ j$T
1.每个成员分别按自己的方式对齐,并能最小化长度 xDekC~Zq
2.复杂类型(如结构)的默认对齐方式是它最长的成员的对齐方式,这样在成员是复杂类型时,可以最小化长度 xOg|<Nnl
3.对齐后的长度必须是成员中最大的对齐参数的整数倍,这样在处理数组时可以保证每一项都边界对齐 *kF/yN
i>G:*?a
rk,64(
网友xue23(xue23) 的答案和分析: V_v+i c^
wod{C !
有程序查一下各个变量的内存地址得知: >.C$2bW<L
各个变量在内存中的位置为 r
z@%rOWV
c***aa** v[x 5@$
bbbb**** #3?"#),q
dddddddd Ue,eEer
测试代码为: 23p.g5hJi
s2 ss; 5HL>2
e[
cout << "ss.c = " << &ss << endl ; a04S&ezj
cout << "ss.d.a = " <<&ss.d.a << endl; {/?{UbU
cout << "ss.d.b = " <<&(ss.d.b) < cout << "ss.d = " <<&ss.e << endl; em^2\*sxpA
print out 各个变量的内存地址不就可以看出来了吗。 WRAv>s9
>[T6/#M
所以答案是24,2. }c4F}Cy
uF|[MWcy0#
但是我的想像中应该是这样的分布情况: +U<Ae^V
c******* S*3$1BTl
aa**bbbb >B;S;_5=
dddddddd q4"^G:
aG@GJ@w
不知为什么会c和a放在一起,组成8位长度。