Intel和微软同时出现的C语言面试题 0&fO)de96
#pragma pack(8) g(X`.0
6{^\7`
struct s1{ +>1?ck
short a; t3?I4HQ
long b; #9r}Kr=P
}; zj]
g^c;
8<T~AU8'*
struct s2{ sRZ<c
char c; F(."nUrf
s1 d; T(Q ~b
long long e; dmXfz D
}; wT- <#+L\
=H23eOS_#
#pragma pack() 0wNlt#G;{
xg7KU&
问 ]NBx5m+y@i
1.sizeof(s2) = ? B0gD4MX/
2.s2的s1中的a后面空了几个字节接着是b? >g>r_0.
r<n:o7
'dh{q`#0
Ns1n|^9
如果您知道答案请在讨论中写出,以下是部份网友的答案,供参考: et~D9='E
~!2fUewEu
网友rwxybh(行云)的答案: ;SjNZi)4d
内存布局是 0iZeU:FE
1*** 11** ,G46i)E\
1111 **** aXq ig&:
1111 1111
ebJTrh <{
'Ca;gi !U
所以答案就是24和3 Ri`6X_xU
Mb[4_Dc
下面是一个测试的程序,试一试就知道了,我用的是VC2005 ttJ'6lGXh
L5zCL0j`
#pragma pack(8) {V(~
<F&XT@
struct s1{ o938!jML_
short a; // 2 BYtes `Rfe*oAf
long b; // 4 Bytes 5NN;Fw+
}; k)Lhzr[
struct s2{ 1;c># 20
char c; // 1 Byte \xggIW.^0
s1 d; // 8 Bytes |;~2y>E
long long e; // 8 Bytes fPKpV`Hr3
}; U`EOun,
// 1*** 11** dL+yd0b*
// 1111 **** '{.4~:
// 1111 1111 4.wrY6+V
//
X)iI]
#"!ga)a%L
// 00 01 02 03 04 05 06 07 x+za6e_k"
// 00 01 02 03 04 05 06 07 -hm/lxyU
// 00 01 02 03 04 05 06 07 :w5g!G?z
// oVZzvK(zR
#pragma pack() }za pN
v
Y7g%nz[[
int main(int argc, char* argv[]) N2}Y8aR~
{ ;qUB[Kw
s2 a; >lqo73gM9
char *p = (char *)&a; RV{%@1Pu
for(int i=0;i<24;++i) 8'zl\:@N
p = (char)(i%8); O/Hj-u6&A
printf("%d\n",sizeof(a)); NkNFx<9T
printf("c=0x%lx\n",a.c); z\UXnRL
printf("d.a=0x%x\n",a.d.a); .-T P1C
printf("d.b=0x%x\n",a.d.b); xFThs,w
printf("e=0x%llx\n",a.e); i ?M-~EKu
return 0; n.'Ps+G(
} 9)S3{i6w
结果: zb4@U=?w}
24 <+q`Dk
c=0x0 B[7,Hy,R
d.a=0x504 {.e+?V2>_
d.b=0x3020100 Z&iW1
e=0x706050403020100 ,:J[|9
yl@Nyu
S _U |w9q
网友 redleaves (ID最吊的网友)的答案和分析: 8LPWT! S
u
ynudO
如果代码: zY*~2|q,s
#pragma pack(8) Cc{{9Ud
struct S1{ $,/E"G`
char a; N3\RXXY
long b; '-N5F
}; H?Sv6W.~
struct S2 { <>f;g"qS
char c; ;P ju O
struct S1 d; -eh .Tk
long long e; ackeq#
}; s1::\&`za
#pragma pack() )i:*r8*~
sizeof(S2)结果为24. O#[b NLV
成员对齐有一个重要的条件,即每个成员分别对齐.即每个成员按自己的方式对齐. UNiK6h_%
也就是说上面虽然指定了按8字节对齐,但并不是所有的成员都是以8字节对齐.其对齐的规则是,每个成员按其类型的对齐参数(通常是这个类型的大小)和指定对齐参数(这里是8字节)中较小的一个对齐.并且结构的长度必须为所用过的所有对齐参数的整数倍,不够就补空字节. :5j+^/
ZQKo ]Kdr
S1中,成员a是1字节默认按1字节对齐,指定对齐参数为8,这两个值中取1,a按1字节对齐;成员b是4个字节,默认是按4字节对齐,这时就按4字节对齐,所以sizeof(S1)应该为8; JM/\n4ea:
S2中,c和S1中的a一样,按1字节对齐,而d 是个结构,它是8个字节,它按什么对齐呢?对于结构来说,它的默认对齐方式就是它的所有成员使用的对齐参数中最大的一个,S1的就是4.所以,成员d就是按4字节对齐.成员e是8个字节,它是默认按8字节对齐,和指定的一样,所以它对到8字节的边界上,这时,已经使用了12个字节了,所以又添加了4个字节的空,从第16个字节开始放置成员e.这时,长度为24,已经可以被8(成员e按8字节对齐)整除.这样,一共使用了24个字节. &0bq3JGW
a b :8/ 6dx@Y(
S1的内存布局:11**,1111, rX5"p!z
c S1.a S1.b d F|m &n&
S2的内存布局:1***,11**,1111,****11111111 ,\&r\!=
=Gzs+6A8
这里有三点很重要: S~fP$L5
1.每个成员分别按自己的方式对齐,并能最小化长度 McS]aJfrk
2.复杂类型(如结构)的默认对齐方式是它最长的成员的对齐方式,这样在成员是复杂类型时,可以最小化长度 ZD|F"v.
3.对齐后的长度必须是成员中最大的对齐参数的整数倍,这样在处理数组时可以保证每一项都边界对齐 H$WD7/?j
l8+)Xk>
*$DD+]2
网友xue23(xue23) 的答案和分析: }s'=w]m
jz=V*p}6
有程序查一下各个变量的内存地址得知: y*sVimx
各个变量在内存中的位置为 y!x[N!a
c***aa** M"p%CbcI]
bbbb**** C_q2bI
dddddddd oO3^9?Z
测试代码为: <
-W 8
s2 ss; ge?0>UU;~
cout << "ss.c = " << &ss << endl ; ND.(N'/O
cout << "ss.d.a = " <<&ss.d.a << endl; I9xu3izAmR
cout << "ss.d.b = " <<&(ss.d.b) < cout << "ss.d = " <<&ss.e << endl; F[jqJzCz
print out 各个变量的内存地址不就可以看出来了吗。 k1yqerA
IOC$jab@
所以答案是24,2. `5Z'8^
,38M6yD
但是我的想像中应该是这样的分布情况: 3$P
c******* acUyz2x
aa**bbbb "m6G;cv
dddddddd mDv<d =p!
*6AqRE
不知为什么会c和a放在一起,组成8位长度。