Intel和微软同时出现的C语言面试题 ~b3xn T
#pragma pack(8) lLmVat(
_<pG}fmR
struct s1{ 9C|T/+R
short a; #bsR L8@
long b; Q7"KgqpQ3
}; /B|#GJ\\3
-R~;E[
{%
struct s2{ @]H&(bw
char c; v^[tK2&v
s1 d; ]AERi]
B
long long e; #8;^ys1f
}; Iy8gQdI
xb8fV*RO8A
#pragma pack() q,aWF5m@
?F
AsV&y
问 H",yVD
1.sizeof(s2) = ? ^yy\CtG
2.s2的s1中的a后面空了几个字节接着是b? W$:;MY>0f
P%'bSx1
Eqp?cKrji
eJ'2CM6
如果您知道答案请在讨论中写出,以下是部份网友的答案,供参考: ,EcmMI^A
L.U [eH
网友rwxybh(行云)的答案: |oSyyDYWP
内存布局是 C([;JO
11[
1*** 11** %L/Wc,My
1111 **** e<~uU9
lg1
1111 1111 T-fW[][&$
zclt2?
所以答案就是24和3 "h$A. S
=<`9T_S 16
下面是一个测试的程序,试一试就知道了,我用的是VC2005 zoC/Hm
k W/3
Aq7r
#pragma pack(8) b'Mg
SQ>.P
struct s1{ hP3I_I[qF}
short a; // 2 BYtes t.lm`=
long b; // 4 Bytes g@MTKqs
}; Y_Ej-u+>{
struct s2{ J%j#gyTU
char c; // 1 Byte +c}fDrr)
s1 d; // 8 Bytes -H Zvz[u
long long e; // 8 Bytes |;OM,U2
}; h(GgkTj4+
// 1*** 11** aWOApXJ
// 1111 **** RBt"7 '
// 1111 1111 eoTOccb!
// 9Hlu%R
.H7"nt^
// 00 01 02 03 04 05 06 07 f
IQ$a>
// 00 01 02 03 04 05 06 07 UbY-)9==
// 00 01 02 03 04 05 06 07 Z%(aBz7Et
// sw{EV0&>m
#pragma pack() ?
Ew>'(Q
;#`Z(A}
int main(int argc, char* argv[]) kRSu6r9
{ 1swh7
s2 a; e)!X9><J
char *p = (char *)&a; d cPh@3
for(int i=0;i<24;++i) kW6}57iV
p = (char)(i%8); qi7dcn@d
printf("%d\n",sizeof(a)); p_B,7@Jl
printf("c=0x%lx\n",a.c); +Nc|cj
printf("d.a=0x%x\n",a.d.a); P)>WIQSr
printf("d.b=0x%x\n",a.d.b); ""CJlqU
printf("e=0x%llx\n",a.e); iu*u|e
return 0; 1m}'Y@I
}
pfZn<n5p
结果: d/P$q MD
24 qL A
c=0x0 #\%GrtM
d.a=0x504 <C#
s0UX
d.b=0x3020100 MSRIG-
e=0x706050403020100 2rPKZ|
tQo"$ JN}
@_N -> l
网友 redleaves (ID最吊的网友)的答案和分析: 9dqD(S#C;"
k?|VFh1
如果代码: q_cqjly<
#pragma pack(8) rAP+nh ans
struct S1{ jDH)S{k
char a; la|#SS95
long b; uZ<Bfrc
}; gJvc<]W8!
struct S2 { iLv"ZqGrw
char c; zx#d_SVi
struct S1 d; ^]E| >~\
long long e; /R9>\}.yJ
}; '
nf"u
#pragma pack() i,;Q
sizeof(S2)结果为24. ~;bwfp_
成员对齐有一个重要的条件,即每个成员分别对齐.即每个成员按自己的方式对齐. FY#`]124*
也就是说上面虽然指定了按8字节对齐,但并不是所有的成员都是以8字节对齐.其对齐的规则是,每个成员按其类型的对齐参数(通常是这个类型的大小)和指定对齐参数(这里是8字节)中较小的一个对齐.并且结构的长度必须为所用过的所有对齐参数的整数倍,不够就补空字节. 'DntZK
8ne5 B4
S1中,成员a是1字节默认按1字节对齐,指定对齐参数为8,这两个值中取1,a按1字节对齐;成员b是4个字节,默认是按4字节对齐,这时就按4字节对齐,所以sizeof(S1)应该为8; 2R<1^
S2中,c和S1中的a一样,按1字节对齐,而d 是个结构,它是8个字节,它按什么对齐呢?对于结构来说,它的默认对齐方式就是它的所有成员使用的对齐参数中最大的一个,S1的就是4.所以,成员d就是按4字节对齐.成员e是8个字节,它是默认按8字节对齐,和指定的一样,所以它对到8字节的边界上,这时,已经使用了12个字节了,所以又添加了4个字节的空,从第16个字节开始放置成员e.这时,长度为24,已经可以被8(成员e按8字节对齐)整除.这样,一共使用了24个字节. R`TM@aaS:
a b pxDZ}4mOh
S1的内存布局:11**,1111, ~5p
`Kg*
c S1.a S1.b d pSV
8!
S2的内存布局:1***,11**,1111,****11111111 g\ <Lb
-VRu^l#
这里有三点很重要: !X[lNtO
1.每个成员分别按自己的方式对齐,并能最小化长度 v oC<
/}E
2.复杂类型(如结构)的默认对齐方式是它最长的成员的对齐方式,这样在成员是复杂类型时,可以最小化长度 :4(7W[r6
3.对齐后的长度必须是成员中最大的对齐参数的整数倍,这样在处理数组时可以保证每一项都边界对齐 Kq-y1h]7H
*2;w;(-s
W%vh7>.
网友xue23(xue23) 的答案和分析: W=F?+KgL
#i)h0ML/e
有程序查一下各个变量的内存地址得知: l9P~,Ec4''
各个变量在内存中的位置为 1AoBsEnd
c***aa** .z+QyNc:
bbbb**** ^0X86
dddddddd _|*3uGo:
测试代码为: U$0#j
s2 ss; b3Y9
cout << "ss.c = " << &ss << endl ; 5%tIAbGW
cout << "ss.d.a = " <<&ss.d.a << endl; eN}FBX#'
cout << "ss.d.b = " <<&(ss.d.b) < cout << "ss.d = " <<&ss.e << endl; .>CqZN,^
print out 各个变量的内存地址不就可以看出来了吗。 ?+`Zef.g
I&>R]DV
所以答案是24,2. 3=;iC6
`
9D8el}uHf
但是我的想像中应该是这样的分布情况: 8V~w3ssz
c******* yDy3;*lE
aa**bbbb )O2^?Q quS
dddddddd <7^_M*F9
W dIr3
不知为什么会c和a放在一起,组成8位长度。