Intel和微软同时出现的C语言面试题 MeAY\V%G=o
#pragma pack(8) /)<kG(Z
zjzEmX
struct s1{ -z%->OUu
short a; KEf1GU6s
long b; ;j+*}|!
}; xc7Rrh]}
'}-QZ$|*
struct s2{ 9WV8ZP
char c; F)@zo/u5L
s1 d; *e:2iM)8~
long long e; 4
[]!Km
}; A=70UL
dJlK'zK
#pragma pack() U8@P/Z9
MPF({Pnx7
问 x6^FpNgQ
1.sizeof(s2) = ? 9#kk5 )J
2.s2的s1中的a后面空了几个字节接着是b? O'QnfpQ*9
12: Q`
XEN-V-Z%*
y.(m#&T
如果您知道答案请在讨论中写出,以下是部份网友的答案,供参考: *:`fgaIDa
O3pd5&^g
网友rwxybh(行云)的答案: .')^4\
内存布局是 Dw
y|mxlFn
1*** 11** E )2/Vn2
1111 **** fB'Jo<C
1111 1111 Dj 6^|R$z&
8?|W-rN
所以答案就是24和3 n#B}p*G
LLoV]~dvUu
下面是一个测试的程序,试一试就知道了,我用的是VC2005 LLMGs: [
'R99m?"
#pragma pack(8) %/ :&L+q
77j"zr7v
struct s1{ ?v'CuWS
short a; // 2 BYtes 735l&(3A\
long b; // 4 Bytes %4BQY>O)@
}; 3Q2NiYg3
struct s2{ @moaa} 1
char c; // 1 Byte Ak$9\Sl
s1 d; // 8 Bytes 4ywtE}mp
long long e; // 8 Bytes vG=Pi'4XXo
}; =\\rk,F
// 1*** 11** .k#O[^~]
// 1111 **** Cv
p#=x0
// 1111 1111 #Yy5@A}`o
// 3_T'0x\FP
u=E &jL5U
// 00 01 02 03 04 05 06 07 SzFh
// 00 01 02 03 04 05 06 07 #MbY+[Y@v
// 00 01 02 03 04 05 06 07 #jO2Zu2`}
// NGEE'4!i7T
#pragma pack() n7zM;@{7
\Rha7O
int main(int argc, char* argv[]) = \K/ulZo
{ |:u5R%
s2 a; G=C2l#
Ae!
char *p = (char *)&a; R@`xS<`L/
for(int i=0;i<24;++i) % 3fpIzm
p = (char)(i%8); c;=St1eoz
printf("%d\n",sizeof(a)); 0
t/mLw&
printf("c=0x%lx\n",a.c); !"aGo1$$
printf("d.a=0x%x\n",a.d.a); T8x /&g''
printf("d.b=0x%x\n",a.d.b); @Y+kg
printf("e=0x%llx\n",a.e); [FBc&HN
return 0; 9_Z_5w;h
} #W8c)gkG9
结果: YF %]%^n
24 nhd.c2t\
c=0x0 M3dUGM
d.a=0x504 ZvK3Su)f1
d.b=0x3020100 @(."[O:
e=0x706050403020100 -W:@3\{
5r;)Ppo
dkg+_V!
网友 redleaves (ID最吊的网友)的答案和分析: @9k3}x K
h,K&R8S
如果代码: pTJ_DH
#pragma pack(8) )5Cqyp~P
struct S1{ >z,Y%A
char a; &?gcnMg$,J
long b; R/2L9Lcv
}; HD,6
struct S2 { n"R$b:
char c; OSom-?|w
struct S1 d; P8tCzjrV
long long e; jT;'T$
}; TQvjU!>
#pragma pack() LOgB_$9_3
sizeof(S2)结果为24. FtWO[*#
成员对齐有一个重要的条件,即每个成员分别对齐.即每个成员按自己的方式对齐. rAgp cp}
也就是说上面虽然指定了按8字节对齐,但并不是所有的成员都是以8字节对齐.其对齐的规则是,每个成员按其类型的对齐参数(通常是这个类型的大小)和指定对齐参数(这里是8字节)中较小的一个对齐.并且结构的长度必须为所用过的所有对齐参数的整数倍,不够就补空字节. d Z+7S`{
NVDIuh
S1中,成员a是1字节默认按1字节对齐,指定对齐参数为8,这两个值中取1,a按1字节对齐;成员b是4个字节,默认是按4字节对齐,这时就按4字节对齐,所以sizeof(S1)应该为8; g26 l:1P
S2中,c和S1中的a一样,按1字节对齐,而d 是个结构,它是8个字节,它按什么对齐呢?对于结构来说,它的默认对齐方式就是它的所有成员使用的对齐参数中最大的一个,S1的就是4.所以,成员d就是按4字节对齐.成员e是8个字节,它是默认按8字节对齐,和指定的一样,所以它对到8字节的边界上,这时,已经使用了12个字节了,所以又添加了4个字节的空,从第16个字节开始放置成员e.这时,长度为24,已经可以被8(成员e按8字节对齐)整除.这样,一共使用了24个字节. qc.9GC
a b J>nta?/,X
S1的内存布局:11**,1111, NCm=l
c S1.a S1.b d 472'P
S2的内存布局:1***,11**,1111,****11111111 P)ne^_
-'i[/{
这里有三点很重要: h[C XH"
1.每个成员分别按自己的方式对齐,并能最小化长度 Aiqb*v$
2.复杂类型(如结构)的默认对齐方式是它最长的成员的对齐方式,这样在成员是复杂类型时,可以最小化长度 M2.*]AL
3.对齐后的长度必须是成员中最大的对齐参数的整数倍,这样在处理数组时可以保证每一项都边界对齐 6O@Lx]t
l
5f'R
U1kW1L}B
网友xue23(xue23) 的答案和分析: nYj7r*e[
q@4Cw&AI+
有程序查一下各个变量的内存地址得知: FE06,i\{
各个变量在内存中的位置为 ~0vNs2D,S
c***aa** viVn
bbbb**** R!rMrWX
dddddddd TdoH((nY
测试代码为:
Fo]]j=
s2 ss; i-x/h-
cout << "ss.c = " << &ss << endl ; O[=W%2I!i
cout << "ss.d.a = " <<&ss.d.a << endl; Zh?n;n}
cout << "ss.d.b = " <<&(ss.d.b) < cout << "ss.d = " <<&ss.e << endl; M@0S*[O{"
print out 各个变量的内存地址不就可以看出来了吗。 )EN,Ry
26j-1c!NGd
所以答案是24,2. `EiL~*
LBcqFvj{&
但是我的想像中应该是这样的分布情况: %Wc$S]>i
c******* ;[|+tO_
aa**bbbb {|e7^_ ke
dddddddd E/E|*6R
&(20*Vn,O
不知为什么会c和a放在一起,组成8位长度。