Intel和微软同时出现的C语言面试题 cw3JSz9
#pragma pack(8) jWb;Xk4
-I1Ne^DZn4
struct s1{ Pnb?NVP!^9
short a; j)Z3m @Ii5
long b; YoD1\a|
}; cad%:%p
NpRT\cx3
struct s2{ /easmf]
char c; xbex6i"ZE
s1 d; )j6VROt
long long e; DU g
}; ]R^?Pa1Te4
}U$Yiv
#pragma pack() ]A;zY%>
4ze-N8<[
问 #UH|,>W6
1.sizeof(s2) = ? qyMR0ai-
2.s2的s1中的a后面空了几个字节接着是b? ZHxdrX)
\WD}@6)
~
<C\snB
/H+j6*}r
如果您知道答案请在讨论中写出,以下是部份网友的答案,供参考: a;AvY O
}Vw"7
网友rwxybh(行云)的答案: IfoeHAWX
内存布局是 BH0@WG7F
1*** 11**
WpX)[au
1111 **** EfY|S3Av
1111 1111 m#+0uZm(
]|[,N>
所以答案就是24和3 u\zRWX
F9q<MTh
下面是一个测试的程序,试一试就知道了,我用的是VC2005 C=}YKsi|R|
u"-q"0
#pragma pack(8) *]%{ttR~
]zHUF!a*
struct s1{ x$9UHEb kM
short a; // 2 BYtes * a xOen
long b; // 4 Bytes H kDT14 `&
}; >\hu1C|W
struct s2{ W:{1R&$l
char c; // 1 Byte = >)S\Dfi
s1 d; // 8 Bytes a4FvQH#j
long long e; // 8 Bytes kS[xwbE
}; .63:G<
// 1*** 11** 5haJPWG|'
// 1111 **** C|c'V-f
// 1111 1111 d^X;XVAvP
// h^ ex?
D0,U2d
// 00 01 02 03 04 05 06 07 hVRpk0IJDK
// 00 01 02 03 04 05 06 07 #KZ6S9>@
// 00 01 02 03 04 05 06 07 RKaCX:
// gW'aK>*c
#pragma pack() P?*$Wf,~n
;X6FhQ;{*0
int main(int argc, char* argv[]) *M;!{)m?
{ -~eNC^t;W
s2 a; !+&"y K@J
char *p = (char *)&a; \{L!hAw
for(int i=0;i<24;++i) >6 [{\uPK
p = (char)(i%8); Px&*&^Gf[b
printf("%d\n",sizeof(a)); [Y.3miE
printf("c=0x%lx\n",a.c); [gFpFz|b<
printf("d.a=0x%x\n",a.d.a); P6*IR|
printf("d.b=0x%x\n",a.d.b); yhQv $D,^f
printf("e=0x%llx\n",a.e); g*Nc+W](P>
return 0; t {tcy$bw
} 9mkt.>$
结果: ,EW-21
24 HjKj.fV
c=0x0 zC6,m6Dv
d.a=0x504 :.6kXX'~
d.b=0x3020100 'mj0+c$
e=0x706050403020100 1HxE0>
U/&!F
xN0n0
网友 redleaves (ID最吊的网友)的答案和分析: &AH@|$!E
A!&p,KfT5+
如果代码: hZ-No
#pragma pack(8) UOH2I+@V
struct S1{ ! FbW7"yE
char a; 0V
,R|Ln
long b; /\_`Pkd3m
}; 1pogk0h.:
struct S2 { N~g@
char c; =7ul,
struct S1 d; fb[f >1|
long long e; &'9 Jy'(X
}; a) GLz
#pragma pack() *A.E?9pL\
sizeof(S2)结果为24. HcwqVU
成员对齐有一个重要的条件,即每个成员分别对齐.即每个成员按自己的方式对齐. %,$/wh)<V
也就是说上面虽然指定了按8字节对齐,但并不是所有的成员都是以8字节对齐.其对齐的规则是,每个成员按其类型的对齐参数(通常是这个类型的大小)和指定对齐参数(这里是8字节)中较小的一个对齐.并且结构的长度必须为所用过的所有对齐参数的整数倍,不够就补空字节. qQ[&FjTO`
(1gfb*L
S1中,成员a是1字节默认按1字节对齐,指定对齐参数为8,这两个值中取1,a按1字节对齐;成员b是4个字节,默认是按4字节对齐,这时就按4字节对齐,所以sizeof(S1)应该为8; sL]KBux
S2中,c和S1中的a一样,按1字节对齐,而d 是个结构,它是8个字节,它按什么对齐呢?对于结构来说,它的默认对齐方式就是它的所有成员使用的对齐参数中最大的一个,S1的就是4.所以,成员d就是按4字节对齐.成员e是8个字节,它是默认按8字节对齐,和指定的一样,所以它对到8字节的边界上,这时,已经使用了12个字节了,所以又添加了4个字节的空,从第16个字节开始放置成员e.这时,长度为24,已经可以被8(成员e按8字节对齐)整除.这样,一共使用了24个字节. '`=z52
a b ,TaaX I
S1的内存布局:11**,1111, -qz;
c S1.a S1.b d -m)N~>{qS
S2的内存布局:1***,11**,1111,****11111111 5mdn77F_
2 /O/h
这里有三点很重要: o:jLM7$=
1.每个成员分别按自己的方式对齐,并能最小化长度 B P%>J^
2.复杂类型(如结构)的默认对齐方式是它最长的成员的对齐方式,这样在成员是复杂类型时,可以最小化长度 :<f7;.
3.对齐后的长度必须是成员中最大的对齐参数的整数倍,这样在处理数组时可以保证每一项都边界对齐 #r M/
hu.c&Q>
p<
Emy%
网友xue23(xue23) 的答案和分析: v??}d
-S\74hA
有程序查一下各个变量的内存地址得知: Z?|\0GR+`5
各个变量在内存中的位置为 hX(:xc
c***aa** TWkuR]5
bbbb**** o%X@Bz
dddddddd IT]D;
测试代码为: bS_fWD-
s2 ss; p6u"$)wt
cout << "ss.c = " << &ss << endl ; Tq[=&J
cout << "ss.d.a = " <<&ss.d.a << endl; 9{\eE]0
cout << "ss.d.b = " <<&(ss.d.b) < cout << "ss.d = " <<&ss.e << endl; vQ"EI1=7Z
print out 各个变量的内存地址不就可以看出来了吗。 K0_/;a] |
`J \1t
K{
所以答案是24,2. I`:nb
JPW+(n|g
但是我的想像中应该是这样的分布情况: [3h~y7
c******* 6=a($s!
aa**bbbb 26 un=
dddddddd 0@z=0}0Z
/M(FuV
不知为什么会c和a放在一起,组成8位长度。