Intel和微软同时出现的C语言面试题 F Bk_LEcX
#pragma pack(8) VdC,M;/=Z
|,)=-21&;
struct s1{ TQ`4dVaf
short a; `=QRC.b
long b; &)Z!A*w]
}; K3I|d;Y~X!
A8jj]J+
struct s2{ }<7S%?TY
char c; GYJ
lX
s1 d; &ZR} Z7E*=
long long e; V'Z Z4og
}; uW{;@ 7N
}@Dgr)*+
#pragma pack() B\mRHV!
hH3~O`~
问 [OU[i(,{
1.sizeof(s2) = ? Z8xKg
2.s2的s1中的a后面空了几个字节接着是b? +BaZl<ZP1s
|f}1bJE+
jMUN|(=Y
~u^MRe|`
如果您知道答案请在讨论中写出,以下是部份网友的答案,供参考: Jv[c?6He
?ypX``3#s7
网友rwxybh(行云)的答案: 93]67PL#+
内存布局是 ]hHL[hoFC
1*** 11** 9esMr0*=
1111 **** W!=X_
1111 1111 xZc].l6
X8uAwHa6F
所以答案就是24和3 y(92 Th$
81jVjf?`
下面是一个测试的程序,试一试就知道了,我用的是VC2005 .KeZZLH
i"Z
#pragma pack(8) z7$,m#tw
Ng 3r`S"_<
struct s1{ 7,BULs\g
short a; // 2 BYtes lk/[xQ/
long b; // 4 Bytes [!'fE#"a
}; ymo].
struct s2{ +>*! 3x+sE
char c; // 1 Byte J&w'0
s1 d; // 8 Bytes 1Vi3/JM@
long long e; // 8 Bytes D\CjR6DE
}; u+_6V
// 1*** 11** 6aq=h`Y
// 1111 **** [,?5}'we
// 1111 1111 XtP5IN\S
// *74VrAo
,2MLYW,
// 00 01 02 03 04 05 06 07 ?#]wxH,
// 00 01 02 03 04 05 06 07 ^Yg}>?0
// 00 01 02 03 04 05 06 07 VlbS\Y.
// wRsh@I<
#pragma pack() Mep
ct
q!!gn1PT(T
int main(int argc, char* argv[]) DYej<T'?3
{ DGrk}
s2 a; -Ed<Kl
char *p = (char *)&a; V
X"!a
for(int i=0;i<24;++i) _i@4R<
p = (char)(i%8); X :wfmb
printf("%d\n",sizeof(a)); ~[ZRE @
printf("c=0x%lx\n",a.c); 3<A$lG
printf("d.a=0x%x\n",a.d.a);
qC4Q+"'
printf("d.b=0x%x\n",a.d.b); `-)Hot)
printf("e=0x%llx\n",a.e); 1n-+IR"
return 0; FofeQ
} H:5- S
结果: d,+a}eTP'
24 e4mAKB
s!
c=0x0 /OtLIM+7~{
d.a=0x504 AR?1_]"=
d.b=0x3020100 (JI[y"2
e=0x706050403020100 J]4pPDm
<%ba
3<sg
_|f_%S8a_=
网友 redleaves (ID最吊的网友)的答案和分析: {$P')>/
yO*HJpc
如果代码: #sHt3z)6I
#pragma pack(8) $Si|;j$?
struct S1{ ==]BrhZK
char a; &|Cd1z#?
long b; $ts1XIK%
}; ,(y6XUV~
struct S2 { pr.+r?la]
char c; 0hv}*NYd
struct S1 d; 45aFH}w:
long long e; ApSzkPv*
}; ^jB17z[
#pragma pack() +.pri
sizeof(S2)结果为24. j[Z<|Da
成员对齐有一个重要的条件,即每个成员分别对齐.即每个成员按自己的方式对齐. [$e\?c
也就是说上面虽然指定了按8字节对齐,但并不是所有的成员都是以8字节对齐.其对齐的规则是,每个成员按其类型的对齐参数(通常是这个类型的大小)和指定对齐参数(这里是8字节)中较小的一个对齐.并且结构的长度必须为所用过的所有对齐参数的整数倍,不够就补空字节. <;P40jDL
S!6 ? b5
S1中,成员a是1字节默认按1字节对齐,指定对齐参数为8,这两个值中取1,a按1字节对齐;成员b是4个字节,默认是按4字节对齐,这时就按4字节对齐,所以sizeof(S1)应该为8; 9?38/2kX4
S2中,c和S1中的a一样,按1字节对齐,而d 是个结构,它是8个字节,它按什么对齐呢?对于结构来说,它的默认对齐方式就是它的所有成员使用的对齐参数中最大的一个,S1的就是4.所以,成员d就是按4字节对齐.成员e是8个字节,它是默认按8字节对齐,和指定的一样,所以它对到8字节的边界上,这时,已经使用了12个字节了,所以又添加了4个字节的空,从第16个字节开始放置成员e.这时,长度为24,已经可以被8(成员e按8字节对齐)整除.这样,一共使用了24个字节. :c}"a(|
a b u6MHdCJ0y
S1的内存布局:11**,1111, ]9hXiY
c S1.a S1.b d 0 P2lq
S2的内存布局:1***,11**,1111,****11111111 P+<4w
7 <<`9,
这里有三点很重要: g|=1U
1.每个成员分别按自己的方式对齐,并能最小化长度 t`Lh(`
2.复杂类型(如结构)的默认对齐方式是它最长的成员的对齐方式,这样在成员是复杂类型时,可以最小化长度 7N4)T'B
3.对齐后的长度必须是成员中最大的对齐参数的整数倍,这样在处理数组时可以保证每一项都边界对齐 w:HRzU>
\ Dccf_(Pb
\m%Z;xKG
网友xue23(xue23) 的答案和分析: %n)H(QPW
<sw fYT!N
有程序查一下各个变量的内存地址得知: kK%@cIXS3
各个变量在内存中的位置为 CAbR+y
c***aa** vp&N)t_
bbbb**** mbZn[D_zi
dddddddd (U([T -H
测试代码为: Lc! t
s2 ss; cTa$t :K@
cout << "ss.c = " << &ss << endl ; 6R#.AD\
cout << "ss.d.a = " <<&ss.d.a << endl; PTP0 _|K
cout << "ss.d.b = " <<&(ss.d.b) < cout << "ss.d = " <<&ss.e << endl; ##5e:<c&[
print out 各个变量的内存地址不就可以看出来了吗。 2e^6Od!Y?
*6/OLAkyF
所以答案是24,2. x%`tWE|
1<D^+FC4b,
但是我的想像中应该是这样的分布情况: b"pN; v
c******* /C6$B)w_*{
aa**bbbb 34:Y_*
dddddddd !t!'
mTBSntZx
不知为什么会c和a放在一起,组成8位长度。