Intel和微软同时出现的C语言面试题 .]0u#fz0y
#pragma pack(8) .}wVM`81z
c,K)*HB
struct s1{ #s\HiO$BT
short a; rY~!hZ
long b; aw\\oN*
}; TQ{rg2_T
_XO3ml\x@
struct s2{ n7J6YtUwP
char c; t+,'
s1 d; 9ff6Apill
long long e; y.O%
}; ]WsQ=
zA
; 7Nv$3
#pragma pack() J@Qt(rRxi
j.?c~Fh
问 ,v#F6xv8
1.sizeof(s2) = ? :"vW;$1
}
2.s2的s1中的a后面空了几个字节接着是b? ?F^$4:
k3HPY}-
@%oHt*u
P?#I9y7iP
如果您知道答案请在讨论中写出,以下是部份网友的答案,供参考: EO_:C9=d{
a7]wPXKq
网友rwxybh(行云)的答案: 8NE+G.:G
内存布局是 g+X .8>=
1*** 11** U9*uXD1\
1111 **** .+@;gVZx1
1111 1111 ag_RKlM3
zF)&o}
所以答案就是24和3 o4^|n1vN
i-<1M|f
下面是一个测试的程序,试一试就知道了,我用的是VC2005 XY_zFF
s U|\? pJ
#pragma pack(8) k%|Sl>{Ir
!Qqi%
struct s1{ pL&
Zcpx
short a; // 2 BYtes HGwSsoS
long b; // 4 Bytes `X:o]t@
}; A(2\Gfe
struct s2{ __3s3YG
char c; // 1 Byte /O^aFIxk
s1 d; // 8 Bytes InAx;2'A:
long long e; // 8 Bytes Wq+a5[3"
}; $ #*";b)QY
// 1*** 11** _x2i=SFo*$
// 1111 **** AgBXB%).
// 1111 1111 1@i|[dq
// h:4Uv}Z
Sb/`a~q^
// 00 01 02 03 04 05 06 07 G[bWjw86O
// 00 01 02 03 04 05 06 07 mRNA ,*
// 00 01 02 03 04 05 06 07 Hdn%r<+c
// '&;s32']}
#pragma pack() a(eKb2 CX
pef)c,U$
int main(int argc, char* argv[]) _oILZ,
{ Nuebxd
s2 a; ~~B`\!n7
char *p = (char *)&a; eXYf"hU,
for(int i=0;i<24;++i) YAc~,N
p = (char)(i%8); S#:yl>2
printf("%d\n",sizeof(a)); Zw`9B
printf("c=0x%lx\n",a.c); e!B>M{
printf("d.a=0x%x\n",a.d.a); V?zCON
printf("d.b=0x%x\n",a.d.b);
# h/#h\
printf("e=0x%llx\n",a.e); 2LTMt?
return 0; +W7#G `>
} 6z'3e\x
结果: O u-/dE%
24 %FhUjHm
c=0x0 !P"@oJ/Yy_
d.a=0x504 JS^QfT,zE
d.b=0x3020100 z*w.A=r
e=0x706050403020100 L|*0
A=6
e*!0|#-
hRFm]q
网友 redleaves (ID最吊的网友)的答案和分析: yP^C)
i>aIuQ`pe
如果代码: w~%Rxdh?8W
#pragma pack(8) tYk!Y/O}
struct S1{ NRI@M5
char a; Pl\r|gS;
long b; sq45fRAi
}; zAkF:^#Y
struct S2 { ?lPyapA]
char c; np6R\Q!&
struct S1 d; \5pBK
long long e; +}eH,
}; 5I6u 2k3
#pragma pack() ~#];&WE
sizeof(S2)结果为24. r?$V;Z
成员对齐有一个重要的条件,即每个成员分别对齐.即每个成员按自己的方式对齐. C)?tf[!_6
也就是说上面虽然指定了按8字节对齐,但并不是所有的成员都是以8字节对齐.其对齐的规则是,每个成员按其类型的对齐参数(通常是这个类型的大小)和指定对齐参数(这里是8字节)中较小的一个对齐.并且结构的长度必须为所用过的所有对齐参数的整数倍,不够就补空字节. *Tum(wWZ
n|N?[)^k
S1中,成员a是1字节默认按1字节对齐,指定对齐参数为8,这两个值中取1,a按1字节对齐;成员b是4个字节,默认是按4字节对齐,这时就按4字节对齐,所以sizeof(S1)应该为8; dI?x(vw
S2中,c和S1中的a一样,按1字节对齐,而d 是个结构,它是8个字节,它按什么对齐呢?对于结构来说,它的默认对齐方式就是它的所有成员使用的对齐参数中最大的一个,S1的就是4.所以,成员d就是按4字节对齐.成员e是8个字节,它是默认按8字节对齐,和指定的一样,所以它对到8字节的边界上,这时,已经使用了12个字节了,所以又添加了4个字节的空,从第16个字节开始放置成员e.这时,长度为24,已经可以被8(成员e按8字节对齐)整除.这样,一共使用了24个字节. }`uFLBG3
a b s|[CvjL#0
S1的内存布局:11**,1111, eD,'M
c S1.a S1.b d kQw%Wpuq[/
S2的内存布局:1***,11**,1111,****11111111 >n"4M~I
wec_=EqK0
这里有三点很重要: %
4Gt^:J"
1.每个成员分别按自己的方式对齐,并能最小化长度 :LxsiDrF[
2.复杂类型(如结构)的默认对齐方式是它最长的成员的对齐方式,这样在成员是复杂类型时,可以最小化长度 wM1&_%N
3.对齐后的长度必须是成员中最大的对齐参数的整数倍,这样在处理数组时可以保证每一项都边界对齐 2)MX<prH
QX+Xi<YE-
Jq*Q;}n
网友xue23(xue23) 的答案和分析: Ly q[gQjr
re)7h$f}
有程序查一下各个变量的内存地址得知: GCj[ySCD
各个变量在内存中的位置为 w'6sJ#ba(
c***aa** {HtW`r1)Tt
bbbb**** y!VL`xV
dddddddd _A~>?gJ;,
测试代码为: 'mTQ=1
s2 ss; Y3JIDT^
cout << "ss.c = " << &ss << endl ; pCC3r t(
cout << "ss.d.a = " <<&ss.d.a << endl; G Ml JM
cout << "ss.d.b = " <<&(ss.d.b) < cout << "ss.d = " <<&ss.e << endl; 8bdx$,$k
print out 各个变量的内存地址不就可以看出来了吗。 &Lbh?C
m Eg3.|
所以答案是24,2. ENy$sS6[D
[4r<WvUaM
但是我的想像中应该是这样的分布情况: GmH`ipi
c******* 3vHkhhYQ
aa**bbbb >zfFvx_q
dddddddd '<U4D
*G8Z[ht%r
不知为什么会c和a放在一起,组成8位长度。