Intel和微软同时出现的C语言面试题 uO>$,s
#pragma pack(8) 2[LT!TT
XgP7
!
struct s1{ .6+j&{WNo!
short a; `+1+0?9
long b; 9
bYoWw
}; *TVr|
to
'0 GCaL*Sd
struct s2{ pvQw+jX
char c; WmP"u7I4
s1 d; :h=];^/E
long long e; 2)h
i(
}; &Hb6
NZ/gp"D?
#pragma pack() YTpSR~!Rj
\eH~1@\S
问 rV)mcfw:Z
1.sizeof(s2) = ? m:d
P,
2.s2的s1中的a后面空了几个字节接着是b? a[]=*(AZI
_)O1v%]"4
9xyj,;P>
+^Eruv+F
如果您知道答案请在讨论中写出,以下是部份网友的答案,供参考: ?P,z^
~dC)EG
网友rwxybh(行云)的答案: )7Gm<r
内存布局是 iKN~fGRc
1*** 11** Mi,yg=V
1111 **** }|%dN*',
1111 1111 [94A?pn[z
;U<;R
所以答案就是24和3 Q}d6+ C
$Lv,e\]
下面是一个测试的程序,试一试就知道了,我用的是VC2005 7f#e#_sM;
>K1)XP
#pragma pack(8) RmY5/IYR|:
b%L8mX
struct s1{ TDs=VTd@Z
short a; // 2 BYtes <w`
R;
long b; // 4 Bytes _(5SiK R
}; oS0l Tf\
struct s2{ Ii%^z?'
char c; // 1 Byte B BbGq8p
s1 d; // 8 Bytes rS\j9@=Y4
long long e; // 8 Bytes fPZt*A__
}; 0z #'=XWk
// 1*** 11** )."_i64
// 1111 **** 6x)7=_:0
// 1111 1111 CeSr~Ikg|
// ynvU$}w ~'
>N62t9Ll[
// 00 01 02 03 04 05 06 07 c [sydl
// 00 01 02 03 04 05 06 07 9u ^PM
// 00 01 02 03 04 05 06 07 ^.p({6H
// Zy|B~.@<j
#pragma pack() So{/V%
N9tH0
int main(int argc, char* argv[]) x2=Bu#Y
{ x^Q:U1
s2 a; P}29wr IZ
char *p = (char *)&a; bGOOC?[UX
for(int i=0;i<24;++i) /W1!mih
p = (char)(i%8); t6m3lq{
printf("%d\n",sizeof(a)); Bha#=>4FU
printf("c=0x%lx\n",a.c); 0_q8t!<xJw
printf("d.a=0x%x\n",a.d.a); y^zII5|s
printf("d.b=0x%x\n",a.d.b); U>w#`Sy[
printf("e=0x%llx\n",a.e); ;{EIx*<d
return 0; }(A`aB_
} yG)xsY V
结果: Xyy;BO:
24 n^B9Mh@
c=0x0 3}(6z"r
d.a=0x504 1)pwR3(^Fz
d.b=0x3020100 r&oR|-2hRk
e=0x706050403020100 .A<G$ db
?
/2l&D~d"
Z8E-(@`q5Q
网友 redleaves (ID最吊的网友)的答案和分析: WHeyE3}p
Yz]c'M@
如果代码: (RVe,0y
#pragma pack(8) o}$uP5M8q
struct S1{ ^MIF+/bQ
char a; N;4bEcWjp
long b; #V&98 F
}; 3.@"GS#"[
struct S2 { m0QE
S
char c; 6!zBLIYFI
struct S1 d; TwlX'iI_;
long long e; vT~ey
}; i)y8MlC{
#pragma pack() g xY6 M4
sizeof(S2)结果为24. 3}dTbr4y
成员对齐有一个重要的条件,即每个成员分别对齐.即每个成员按自己的方式对齐. i0Ejo;dB
也就是说上面虽然指定了按8字节对齐,但并不是所有的成员都是以8字节对齐.其对齐的规则是,每个成员按其类型的对齐参数(通常是这个类型的大小)和指定对齐参数(这里是8字节)中较小的一个对齐.并且结构的长度必须为所用过的所有对齐参数的整数倍,不够就补空字节. Su?e\7aj
k#F |
S1中,成员a是1字节默认按1字节对齐,指定对齐参数为8,这两个值中取1,a按1字节对齐;成员b是4个字节,默认是按4字节对齐,这时就按4字节对齐,所以sizeof(S1)应该为8; s|F}Abx,^
S2中,c和S1中的a一样,按1字节对齐,而d 是个结构,它是8个字节,它按什么对齐呢?对于结构来说,它的默认对齐方式就是它的所有成员使用的对齐参数中最大的一个,S1的就是4.所以,成员d就是按4字节对齐.成员e是8个字节,它是默认按8字节对齐,和指定的一样,所以它对到8字节的边界上,这时,已经使用了12个字节了,所以又添加了4个字节的空,从第16个字节开始放置成员e.这时,长度为24,已经可以被8(成员e按8字节对齐)整除.这样,一共使用了24个字节. /Cy4]1dw
a b mSLA4[4{
S1的内存布局:11**,1111, B|pO2de
c S1.a S1.b d 5;'(^z-bL
S2的内存布局:1***,11**,1111,****11111111 VzfaUAIZl
h ` qlI1]
这里有三点很重要: fh_+M"Y0`
1.每个成员分别按自己的方式对齐,并能最小化长度 -!;2?6R9{
2.复杂类型(如结构)的默认对齐方式是它最长的成员的对齐方式,这样在成员是复杂类型时,可以最小化长度 ;\j7jz^uC
3.对齐后的长度必须是成员中最大的对齐参数的整数倍,这样在处理数组时可以保证每一项都边界对齐 zU7co.G
WX
.Ax$fT
_D~l2M
网友xue23(xue23) 的答案和分析: K&ZN!VN/p
} I>6 8dS[
有程序查一下各个变量的内存地址得知: !C\$=\$
各个变量在内存中的位置为 9d&@;&al
c***aa** ^POHQQ
bbbb**** ypU-/}Cf,
dddddddd dUN{@a\R0
测试代码为: '
`
_TFTO
s2 ss; 4>
k"$l/:
cout << "ss.c = " << &ss << endl ; /T_{k.
cout << "ss.d.a = " <<&ss.d.a << endl; L $L/5/
cout << "ss.d.b = " <<&(ss.d.b) < cout << "ss.d = " <<&ss.e << endl; yPY}b_W
print out 各个变量的内存地址不就可以看出来了吗。 '8%jA$o\g
YTpiOPf
所以答案是24,2. PAng(tubl
Gyx4}pV
但是我的想像中应该是这样的分布情况: /tm2b<G
c******* n(I,pF
aa**bbbb $7h]A$$Fv
dddddddd 4Vtug>
Q^\m@7O
:
不知为什么会c和a放在一起,组成8位长度。