Intel和微软同时出现的C语言面试题 ~!9Px j*
#pragma pack(8) /'fDXSdP
\N , ' +
struct s1{ ]NV ]@*`tO
short a; /&as)
long b; 5qkuKF
}; &MZy;Sq
yUmsE-W
struct s2{ Wo+CQH6(
char c; \R\@t]>Y
s1 d; 8{SU?MHQLE
long long e; q,+kPhHEgy
}; "Lq|66
*8.@aX3
#pragma pack() 'Rd*X6dv
I#E(r>KW*
问 s~X*U&}5
1.sizeof(s2) = ? /dJ)TW(Ir
2.s2的s1中的a后面空了几个字节接着是b? _c
]3nzIr
q6JW@GT
h<'5q&y
X0Z-1bs
如果您知道答案请在讨论中写出,以下是部份网友的答案,供参考: 14n="-9
?t0zsq
网友rwxybh(行云)的答案: }i7U}T
内存布局是 \btR^;_\A
1*** 11** Hn9F
gul&
1111 **** Z\=04[
1111 1111 w-H%B`/
c\)&yGE
所以答案就是24和3 ,)rZAI
YP#AB]2\}
下面是一个测试的程序,试一试就知道了,我用的是VC2005 0YpiHoM
S`@6c$y k
#pragma pack(8) IFrb}yH
Go\} A:|s
struct s1{ o d}EM_
short a; // 2 BYtes gJ3OK !/
long b; // 4 Bytes Xm8Z+}i
}; ^\[LrPqe
struct s2{ X(y
char c; // 1 Byte Uc&6=5~Ys\
s1 d; // 8 Bytes d]7|v
r]
long long e; // 8 Bytes \7t5U7v8U
}; -4?xwz9o$7
// 1*** 11** !
nCjA\$
// 1111 **** Q\27\2
// 1111 1111 jKj=#O
// %]chL.s
b@wBR9s
// 00 01 02 03 04 05 06 07 UEEBWz H
// 00 01 02 03 04 05 06 07 pG!(6V-x<E
// 00 01 02 03 04 05 06 07 ,ykPQzO
// "B9[cDM&
#pragma pack() rmPne8D=c(
0Oc}rRH(C
int main(int argc, char* argv[]) 8
_4l"v
p
{ _oJ2]f6KX
s2 a; #ox9&
char *p = (char *)&a; }{&ln
for(int i=0;i<24;++i) *|LbbRu
p = (char)(i%8); ,C{^`Bk-W
printf("%d\n",sizeof(a)); iY
^{wi~?
printf("c=0x%lx\n",a.c); =de<WoKnu2
printf("d.a=0x%x\n",a.d.a); QN_)3lm
printf("d.b=0x%x\n",a.d.b); 7_Ba3+9jpa
printf("e=0x%llx\n",a.e); _/,SZ-C#L4
return 0; (px*R~}
} N>d|A]zH
结果: ;RWW+x8IB
24 Y&vHOA
c=0x0 b:P\=k]8#
d.a=0x504 y$IaXr5L
d.b=0x3020100 /x
e=0x706050403020100 6P;o 6s
brg":V1a
7fTxGm
网友 redleaves (ID最吊的网友)的答案和分析: AH&9Nye8
#_.g2 Y
如果代码: Mjb 1
#pragma pack(8) ?SC3Vzr
struct S1{ ?^LG
hdR
char a; 5ZnSA9?
long b; a(8>n
Z,V
}; =m`l%V[
struct S2 { Bj@x$v#/^
char c; 1^aykrnQ>
struct S1 d; UhsO\ 9}qH
long long e; bt;lq!g
}; |/@0~O(6
#pragma pack() `$J'UXtGc
sizeof(S2)结果为24. {bN Y
成员对齐有一个重要的条件,即每个成员分别对齐.即每个成员按自己的方式对齐. Ns'FH(:
也就是说上面虽然指定了按8字节对齐,但并不是所有的成员都是以8字节对齐.其对齐的规则是,每个成员按其类型的对齐参数(通常是这个类型的大小)和指定对齐参数(这里是8字节)中较小的一个对齐.并且结构的长度必须为所用过的所有对齐参数的整数倍,不够就补空字节. y0,Ft/D
xM&EL>m>L
S1中,成员a是1字节默认按1字节对齐,指定对齐参数为8,这两个值中取1,a按1字节对齐;成员b是4个字节,默认是按4字节对齐,这时就按4字节对齐,所以sizeof(S1)应该为8; G9\EZ\x!
S2中,c和S1中的a一样,按1字节对齐,而d 是个结构,它是8个字节,它按什么对齐呢?对于结构来说,它的默认对齐方式就是它的所有成员使用的对齐参数中最大的一个,S1的就是4.所以,成员d就是按4字节对齐.成员e是8个字节,它是默认按8字节对齐,和指定的一样,所以它对到8字节的边界上,这时,已经使用了12个字节了,所以又添加了4个字节的空,从第16个字节开始放置成员e.这时,长度为24,已经可以被8(成员e按8字节对齐)整除.这样,一共使用了24个字节. 6|QTS|!
a b 43KaL(
S1的内存布局:11**,1111, ucw`;<d8
c S1.a S1.b d z~F37]W3[
S2的内存布局:1***,11**,1111,****11111111 Jf2e<?`
[!W5}=^H
这里有三点很重要: <z,+Eg
1.每个成员分别按自己的方式对齐,并能最小化长度 nt7|f,_J
2.复杂类型(如结构)的默认对齐方式是它最长的成员的对齐方式,这样在成员是复杂类型时,可以最小化长度 Ujf,6=M
3.对齐后的长度必须是成员中最大的对齐参数的整数倍,这样在处理数组时可以保证每一项都边界对齐 bn $)f6%
A*hZv|$0
^Sw2xT$p{j
网友xue23(xue23) 的答案和分析:
4bnt=5]
oWI!u 5
有程序查一下各个变量的内存地址得知: fTBVvY4(
各个变量在内存中的位置为 k=e`*LB\
c***aa** 7m\vRMK
bbbb**** <P-$RX
dddddddd kL|\wci
测试代码为: Y.7}
s2 ss; Hoj8okP
cout << "ss.c = " << &ss << endl ; ?b56AE
cout << "ss.d.a = " <<&ss.d.a << endl; -OWZ6#v(
cout << "ss.d.b = " <<&(ss.d.b) < cout << "ss.d = " <<&ss.e << endl; )#a7'Ba
print out 各个变量的内存地址不就可以看出来了吗。 cM3jnim
t ^m~
所以答案是24,2. s'TY[
Apmw6cc
但是我的想像中应该是这样的分布情况: Y3k[~A7X
c******* T<P0T<
aa**bbbb Ls1B\Aw _
dddddddd ;,k=<]
}-74 f
不知为什么会c和a放在一起,组成8位长度。