Intel和微软同时出现的C语言面试题 ]uypi#[
#pragma pack(8) Xpn\TD<_I
\.O&-oi
struct s1{ Wh| T3&
short a; /z4c>)fV
long b; Y8]@y0(
}; 2vLun
72"H#dy%U
struct s2{ ;h+~xxu=X
char c; [RN]?,
s1 d; 5|*`} ;/y
long long e; N'9T*&o+
}; z8awND
<\ <o#Vq
#pragma pack() C$PS@4'U
'UWkJ2:!
问 {9}CU~R
1.sizeof(s2) = ? oC49c~`8
2.s2的s1中的a后面空了几个字节接着是b? jF0"AA
RPgz"-
J](NCD
S<Gm*$[7
如果您知道答案请在讨论中写出,以下是部份网友的答案,供参考: CN:T$ f|)
^ex\S8j
网友rwxybh(行云)的答案: -ycYQ~R
内存布局是 mc8Q2eQat}
1*** 11** e
}?.3,?
1111 **** iaEQF]*cC
1111 1111 ed#fDMXGQ%
A2:}bb~H
所以答案就是24和3 g,EDE6`8
"4H@&:-(p
下面是一个测试的程序,试一试就知道了,我用的是VC2005 {FI*oO1A~
@QVg5
#pragma pack(8) S\N1qux{
4xmJQ>/
struct s1{ J|f29B-c
short a; // 2 BYtes c_*w<vJ-'
long b; // 4 Bytes -'d:~:1f
}; yiC7)=
struct s2{ s.
A}ydtt
char c; // 1 Byte EUuSN| a
s1 d; // 8 Bytes <JWU@A-.y
long long e; // 8 Bytes rY45.,qWs
}; M=uT8JB
// 1*** 11** gtu<#h(
// 1111 **** 4/`;(*]Fv
// 1111 1111 Z>g>OPu
// rx2'].
|_TI/i>?'
// 00 01 02 03 04 05 06 07 |*NZ^6`@
// 00 01 02 03 04 05 06 07 )/>BgXwH
// 00 01 02 03 04 05 06 07 [M~tH *4"
// O%\cRn8m
#pragma pack() zvdut ,6<
/"?DOsJ.
int main(int argc, char* argv[]) >bf.T7wy
{ mW%8`$rVEO
s2 a; F6[F~^9D
char *p = (char *)&a; Zyz#xMmM
for(int i=0;i<24;++i) {+WY,%e
p = (char)(i%8); e6j1Fa9
printf("%d\n",sizeof(a)); #Z2'Y[@.
printf("c=0x%lx\n",a.c); ?QT6q]|d0+
printf("d.a=0x%x\n",a.d.a); w/m@(EBK
printf("d.b=0x%x\n",a.d.b); '?veMX
printf("e=0x%llx\n",a.e); :IS?si5|
return 0; 37zBX~
} :,JaOn'
结果: 3Xu|hkK\e
24 ~#3{5*
M
c=0x0 Cj8&wz}ez
d.a=0x504 ZgxB7zl//
d.b=0x3020100 >[;@
[4}
e=0x706050403020100 5;0w({1l
B-C$>H^
(^}t
网友 redleaves (ID最吊的网友)的答案和分析: ?lsK?>uU
.u7}p#
如果代码: )C8^'*!
#pragma pack(8) w g?}c ;
struct S1{ (46'#E z[F
char a; $3HqVqF^R
long b; *XhlIQ
}; = ){G
struct S2 { uxU-N
char c; cWkg.ri-x
struct S1 d; dRJ
](Gw
long long e; 'OtTq8G
}; fAULuF
#pragma pack() -`k>(\Q<d
sizeof(S2)结果为24. 9BtGzI\
成员对齐有一个重要的条件,即每个成员分别对齐.即每个成员按自己的方式对齐. b}R_@_<u
也就是说上面虽然指定了按8字节对齐,但并不是所有的成员都是以8字节对齐.其对齐的规则是,每个成员按其类型的对齐参数(通常是这个类型的大小)和指定对齐参数(这里是8字节)中较小的一个对齐.并且结构的长度必须为所用过的所有对齐参数的整数倍,不够就补空字节. 8{G!OBxc\.
N ^rpPq
S1中,成员a是1字节默认按1字节对齐,指定对齐参数为8,这两个值中取1,a按1字节对齐;成员b是4个字节,默认是按4字节对齐,这时就按4字节对齐,所以sizeof(S1)应该为8; kzRvLs4xM
S2中,c和S1中的a一样,按1字节对齐,而d 是个结构,它是8个字节,它按什么对齐呢?对于结构来说,它的默认对齐方式就是它的所有成员使用的对齐参数中最大的一个,S1的就是4.所以,成员d就是按4字节对齐.成员e是8个字节,它是默认按8字节对齐,和指定的一样,所以它对到8字节的边界上,这时,已经使用了12个字节了,所以又添加了4个字节的空,从第16个字节开始放置成员e.这时,长度为24,已经可以被8(成员e按8字节对齐)整除.这样,一共使用了24个字节. 4@-tT;$
a b rc8HZ
S1的内存布局:11**,1111, k-|g
c S1.a S1.b d OOSf<I*>
S2的内存布局:1***,11**,1111,****11111111 >+dSPI
et
1HbX
这里有三点很重要: kBR=a%kG
1.每个成员分别按自己的方式对齐,并能最小化长度 EE 1D>I
2.复杂类型(如结构)的默认对齐方式是它最长的成员的对齐方式,这样在成员是复杂类型时,可以最小化长度 =IMmtOvJ
3.对齐后的长度必须是成员中最大的对齐参数的整数倍,这样在处理数组时可以保证每一项都边界对齐 _h-agn4[i
3<r7"/5
,IPt4EH$
网友xue23(xue23) 的答案和分析: A`3KE9ED
'0+I' _(
有程序查一下各个变量的内存地址得知: ZwMVFC-d
各个变量在内存中的位置为 6LDZ|K@
c***aa** a 20w.6F
bbbb**** iP(MDVg
dddddddd >j=ZB3yZ
测试代码为: U7g`R@
s2 ss; $#hU_vr
cout << "ss.c = " << &ss << endl ; E'f7=ChNF
cout << "ss.d.a = " <<&ss.d.a << endl; &gXL{cK'%
cout << "ss.d.b = " <<&(ss.d.b) < cout << "ss.d = " <<&ss.e << endl; %1A8m-u]M
print out 各个变量的内存地址不就可以看出来了吗。 89&9VX^A
C|&tdh :g
所以答案是24,2. #,#_"
;O hQBAC
但是我的想像中应该是这样的分布情况: 8?nn4]P
c******* s5@BVD'}E
aa**bbbb
BjH|E@z
dddddddd uQ W)pD{_
.:j{d}p}
不知为什么会c和a放在一起,组成8位长度。