Intel和微软同时出现的C语言面试题 )ew[ Ak|
#pragma pack(8) 7bonOt
Y
lHcZi
struct s1{ 'n^2|"$sH
short a; MjQ[^%lfL
long b; 0Oc}rRH(C
}; 8
_4l"v
p
H~[LJ5x
struct s2{ Gpdv]SON{
char c; kUn2RZ6$#
s1 d; qukjS#>+
long long e; PG6[lHmi
}; ShWHHU(QQ
~5r=FF6
#pragma pack() %XJQ0CE<(
Xr?>uqY!M
问 _/,SZ-C#L4
1.sizeof(s2) = ? =PNdP
2.s2的s1中的a后面空了几个字节接着是b? {H=oxa
&GdL 9!hH
/~i.\^HX
Hva2j<h
如果您知道答案请在讨论中写出,以下是部份网友的答案,供参考: X0y?<G1(a
n}< ir!ZTO
网友rwxybh(行云)的答案: [1z{T(dh
内存布局是 xClRO,-
1*** 11** 8yE!7$Mj
1111 **** 5%<TF.;-J
1111 1111 \f(Y:}9
t|;%DA)fjw
所以答案就是24和3 Q0V^PDF
2?GXkPF2;A
下面是一个测试的程序,试一试就知道了,我用的是VC2005 w$gSj/
o" |O
]
#pragma pack(8) CE~r4
f5@.^hi[
struct s1{ :3*`IB !
short a; // 2 BYtes QF\kPk(CtD
long b; // 4 Bytes 3YR *
^
}; QTVa
struct s2{ !L4dUMo
char c; // 1 Byte [ZuVUOm
s1 d; // 8 Bytes "
Wp
long long e; // 8 Bytes +.w[6
}; A?e,U,
// 1*** 11** __8&Jv\
// 1111 **** ~\2;i]|
// 1111 1111 !0`lu_ZN
// XmP;L(wa
I?^aCnU
// 00 01 02 03 04 05 06 07 ^>-+@+(
r
// 00 01 02 03 04 05 06 07 y)P&]&"?
// 00 01 02 03 04 05 06 07 ]de\i=?|
// >GgE,h
#pragma pack() &9RH}zv6
9+}cE**=d
int main(int argc, char* argv[]) > 84e`aGE
{ veV_be{i
s2 a; \fTTkpM
char *p = (char *)&a; #+$ zE#je
for(int i=0;i<24;++i) z^'n*h
p = (char)(i%8); *m*`}9
printf("%d\n",sizeof(a)); d [r-k 2
printf("c=0x%lx\n",a.c); SgiDh dE
printf("d.a=0x%x\n",a.d.a); f_rp<R>Uu
printf("d.b=0x%x\n",a.d.b); q]K'p,'
printf("e=0x%llx\n",a.e); hqL+_|DW
return 0; #00D?nC
} )Bo]=ZTJ^
结果: guU=NQZ
24 Yr=8!iR$
c=0x0 40u7fojg2
d.a=0x504 syRN4
d.b=0x3020100 d.p'pGL
e=0x706050403020100 ;`+`#h3-V
F_
81l<
#ra*f~G
网友 redleaves (ID最吊的网友)的答案和分析: `^x9(i/NE
grspt}
如果代码: h/HHKn
#pragma pack(8) "TNVD"RLY
struct S1{ \^0 !|
char a; B)M&\:
_
long b; V#L'7">VP
}; WqE
'(
struct S2 { &))\2pl
char c; -%,"iaO
struct S1 d; <!F3s`7~
long long e; 5]d{6Nc3P
}; &?y7I Pp
#pragma pack() >?I/;R.-
sizeof(S2)结果为24. FqZgdmwR
成员对齐有一个重要的条件,即每个成员分别对齐.即每个成员按自己的方式对齐. n1,S_Hs
也就是说上面虽然指定了按8字节对齐,但并不是所有的成员都是以8字节对齐.其对齐的规则是,每个成员按其类型的对齐参数(通常是这个类型的大小)和指定对齐参数(这里是8字节)中较小的一个对齐.并且结构的长度必须为所用过的所有对齐参数的整数倍,不够就补空字节. n'M>xq_
FshC )[w,
S1中,成员a是1字节默认按1字节对齐,指定对齐参数为8,这两个值中取1,a按1字节对齐;成员b是4个字节,默认是按4字节对齐,这时就按4字节对齐,所以sizeof(S1)应该为8; u%B&WwHG
S2中,c和S1中的a一样,按1字节对齐,而d 是个结构,它是8个字节,它按什么对齐呢?对于结构来说,它的默认对齐方式就是它的所有成员使用的对齐参数中最大的一个,S1的就是4.所以,成员d就是按4字节对齐.成员e是8个字节,它是默认按8字节对齐,和指定的一样,所以它对到8字节的边界上,这时,已经使用了12个字节了,所以又添加了4个字节的空,从第16个字节开始放置成员e.这时,长度为24,已经可以被8(成员e按8字节对齐)整除.这样,一共使用了24个字节. APq7 f8t
a b g*J@[y;
S1的内存布局:11**,1111, D"^'.DL@wG
c S1.a S1.b d JNi=`X&A
S2的内存布局:1***,11**,1111,****11111111 T<yb#ak
y`So&:1
这里有三点很重要: e;h,V(
1.每个成员分别按自己的方式对齐,并能最小化长度 Skxd<gv
2.复杂类型(如结构)的默认对齐方式是它最长的成员的对齐方式,这样在成员是复杂类型时,可以最小化长度 Qnt5HSSt
3.对齐后的长度必须是成员中最大的对齐参数的整数倍,这样在处理数组时可以保证每一项都边界对齐 e <"/'Ql!k
cU8x Upq
vy9dAl
网友xue23(xue23) 的答案和分析: S&wzB)#'
p!DP`Ouc3\
有程序查一下各个变量的内存地址得知: "r$/
各个变量在内存中的位置为 [Y8S[YY
c***aa** snC/H G7
bbbb**** ?\y%]1
dddddddd 9 <\`nm
测试代码为: 1m)M;^_
s2 ss; |8U;m:AS
cout << "ss.c = " << &ss << endl ; ^B]@Lr E^
cout << "ss.d.a = " <<&ss.d.a << endl; bK*~ol
cout << "ss.d.b = " <<&(ss.d.b) < cout << "ss.d = " <<&ss.e << endl; zk}{ dG^M:
print out 各个变量的内存地址不就可以看出来了吗。 g7n"
^$NJD
所以答案是24,2. rQr!R$t/[
?obm7<
但是我的想像中应该是这样的分布情况: ahGT4d`)9
c******* m3 -9b"
aa**bbbb ea9oakF
dddddddd ZA820A>2!
'*T]fND4
不知为什么会c和a放在一起,组成8位长度。