Intel和微软同时出现的C语言面试题 $0~_)$i:
#pragma pack(8) D89(u.h
0e~4(2xK
struct s1{ ftqeiZ
2
short a; D14i]
long b; qAVZ&:#
}; Z&Z=24q_
-H](2}
struct s2{ FHyyZ{"
char c; s+]6X*)
s1 d; HqKD]1
long long e; tc<HA7vpt~
}; ,6T3:qkkvF
ET=-r
#pragma pack() {r[g.@
X_J(P?
问 $-BM`Zt0;
1.sizeof(s2) = ? X=X
2.s2的s1中的a后面空了几个字节接着是b? dj:6c@n
,a@jg&Mb]
T oK'Pd
.^FdO$"
如果您知道答案请在讨论中写出,以下是部份网友的答案,供参考: oAq<ag\qV
=8 Jq'-da
网友rwxybh(行云)的答案: a.G;s2>
内存布局是 OYk/K70l3
1*** 11** 05[k@f$n
1111 **** ,=t}|!jx
1111 1111 mRD '@n
_*dUH5
所以答案就是24和3 >}!})]Xw9
D"GQlR
下面是一个测试的程序,试一试就知道了,我用的是VC2005 =7%c*O <
A}(Q^|6
#pragma pack(8) y/6%'56uF
%@x.km3e2
struct s1{ `&)uuLn|
short a; // 2 BYtes ~*^aCuq\
long b; // 4 Bytes >Byxb./*
}; H1kxY]_/
struct s2{ {-e|x&-
char c; // 1 Byte 3q$"`w
s1 d; // 8 Bytes OOX[xv!b
long long e; // 8 Bytes !I[|\ 4j
}; ]c$)0O\O
// 1*** 11** ;{K/W.R
// 1111 **** A@#D_[~
// 1111 1111 2VA mL7)
// Jhr3[A
DH{^9HK
// 00 01 02 03 04 05 06 07 ycSC'R
// 00 01 02 03 04 05 06 07 .KzU7
// 00 01 02 03 04 05 06 07 |$.`4h?
// tFYod#
#pragma pack() Jz6zJKcA
v?qU/
int main(int argc, char* argv[]) T!Eyq,]
{ "~ eF%}.
s2 a; .7M:AS>
char *p = (char *)&a; {G4{4D }
for(int i=0;i<24;++i) yM*f}S/
(
p = (char)(i%8); M"<B@p]rk:
printf("%d\n",sizeof(a)); u8i!Fxu
printf("c=0x%lx\n",a.c); QwgP+ M+
printf("d.a=0x%x\n",a.d.a); "1%YtV5R{
printf("d.b=0x%x\n",a.d.b); EnnE@BJ"
printf("e=0x%llx\n",a.e); 6]5e(J{Fz
return 0; YO`V'6\
} o[E|xw
结果: 6,UW5389
24 };s8xGW:k3
c=0x0 tc<ly{ 1c
d.a=0x504 `KUl
XS(
d.b=0x3020100 0}iND$6@a
e=0x706050403020100 z ,q1TU9
AvEd?
1o%E(*M4I
网友 redleaves (ID最吊的网友)的答案和分析: uQ'Izdm
Yl0_?.1 z
如果代码: F{"4cyoou
#pragma pack(8) "$rmy>d
struct S1{ <WRrB
`nO
char a; 5Cjh%rj(jl
long b; U
*']7-
}; k86j&
.m_
struct S2 { =& =#G3f
char c; y?@(%PTp
struct S1 d; |?/,ED+|>D
long long e; brt1Kvu8(
}; xN=:*#Z"pb
#pragma pack() Fl0 :Z
sizeof(S2)结果为24. T+U,?2nF:
成员对齐有一个重要的条件,即每个成员分别对齐.即每个成员按自己的方式对齐. '\I!RAZ
也就是说上面虽然指定了按8字节对齐,但并不是所有的成员都是以8字节对齐.其对齐的规则是,每个成员按其类型的对齐参数(通常是这个类型的大小)和指定对齐参数(这里是8字节)中较小的一个对齐.并且结构的长度必须为所用过的所有对齐参数的整数倍,不够就补空字节. urA
kV#d#
i"J`$u
S1中,成员a是1字节默认按1字节对齐,指定对齐参数为8,这两个值中取1,a按1字节对齐;成员b是4个字节,默认是按4字节对齐,这时就按4字节对齐,所以sizeof(S1)应该为8; &R;Cm]jt
S2中,c和S1中的a一样,按1字节对齐,而d 是个结构,它是8个字节,它按什么对齐呢?对于结构来说,它的默认对齐方式就是它的所有成员使用的对齐参数中最大的一个,S1的就是4.所以,成员d就是按4字节对齐.成员e是8个字节,它是默认按8字节对齐,和指定的一样,所以它对到8字节的边界上,这时,已经使用了12个字节了,所以又添加了4个字节的空,从第16个字节开始放置成员e.这时,长度为24,已经可以被8(成员e按8字节对齐)整除.这样,一共使用了24个字节. K \_JG$(9
a b +_ZXzzcO<
S1的内存布局:11**,1111, 8|Vm6*TY&p
c S1.a S1.b d ^L"ENsOs
S2的内存布局:1***,11**,1111,****11111111 =UMqa;\K
3}9c0%}F
这里有三点很重要: o/5loV3h
1.每个成员分别按自己的方式对齐,并能最小化长度 1&Ruz[F5
2.复杂类型(如结构)的默认对齐方式是它最长的成员的对齐方式,这样在成员是复杂类型时,可以最小化长度 sbV
{RSl
3.对齐后的长度必须是成员中最大的对齐参数的整数倍,这样在处理数组时可以保证每一项都边界对齐 5T- N\)@
P{gy/'PH,
t2 0Es
网友xue23(xue23) 的答案和分析: CFyu9Al
1aBQ.-E-
有程序查一下各个变量的内存地址得知: "[tb-$ER
各个变量在内存中的位置为 &D*22R4{CX
c***aa** %1^E;n
bbbb**** ;;? Zd
dddddddd T5b*Ia
测试代码为: /Dk`vn2 eN
s2 ss; >0Gdxj]\
cout << "ss.c = " << &ss << endl ; =!{
E!3>*D
cout << "ss.d.a = " <<&ss.d.a << endl; Qq*Ks
5
cout << "ss.d.b = " <<&(ss.d.b) < cout << "ss.d = " <<&ss.e << endl; C.Ty\@U
print out 各个变量的内存地址不就可以看出来了吗。 m6
@,J?X
[OK(
所以答案是24,2. J.^%VnrFO9
VYC$Q;Z
但是我的想像中应该是这样的分布情况: @^UnrKSd
c******* l11+sqg
aa**bbbb C|hD^m
dddddddd 1}Mdo&:t
D3xyJ
不知为什么会c和a放在一起,组成8位长度。