Intel和微软同时出现的C语言面试题 [bJnl>A
#pragma pack(8) o#/iR]3
1H7Q[ 2E
struct s1{ H%aLkV!J
short a; FoCkTp+/
long b; $t'I*k^N
}; Y3>\;W*?
a=VT|CX[
struct s2{ @8yFM%
char c; :G/]rDtd
s1 d;
kZ%W?#
long long e; Fg_s'G,`
}; ^?[<!VBI
l}c2l'
#pragma pack() VTfaZ/e.
q.{/{9
问 ?ovGYzUZ
1.sizeof(s2) = ? S'p`ECfVMA
2.s2的s1中的a后面空了几个字节接着是b? *Bsmn!_cB{
#!# X3j
No\&~
=XlIe{
如果您知道答案请在讨论中写出,以下是部份网友的答案,供参考:
w{EU9C
wJ*-K-
网友rwxybh(行云)的答案: w{x(YVSH
内存布局是 eH/\7)z
1*** 11** }/3pC a
1111 **** T<k1?h^7
1111 1111 K/m)f#
}px]
所以答案就是24和3 l{m~d!w`a
G<6grd5PP
下面是一个测试的程序,试一试就知道了,我用的是VC2005 5THS5'
aZGDtzNG5h
#pragma pack(8) Ab<Ok\e5
-8 =u{n
struct s1{ h!CX`pBM
short a; // 2 BYtes $:
m87cR~
long b; // 4 Bytes u;qMo `-
}; '?3z6%
struct s2{ 05I39/T%
char c; // 1 Byte f,inQ2f}d
s1 d; // 8 Bytes k|Yv8+XT
long long e; // 8 Bytes f<altz_\q
}; @Qjl`SL%O^
// 1*** 11** 4{WV
// 1111 **** pQ(eF0KG
// 1111 1111 yXo0z_ G
// A-C)w/7
6cT~irP
// 00 01 02 03 04 05 06 07 |abst&yp
// 00 01 02 03 04 05 06 07 |$?Ux,(6
// 00 01 02 03 04 05 06 07 aevG<|qP
// 'EET3RK-S
#pragma pack() 'L|GClc6)
SA+%c)j29
int main(int argc, char* argv[]) n!eqzr{
{ K0RYI69_
s2 a; bZay/ Zkj
char *p = (char *)&a; 0mD;.1:
for(int i=0;i<24;++i) jvc?hUcLKT
p = (char)(i%8); $<
K)fbG
printf("%d\n",sizeof(a)); ; (0(8G
printf("c=0x%lx\n",a.c); ENx@Ex
printf("d.a=0x%x\n",a.d.a); ml33qXW:
printf("d.b=0x%x\n",a.d.b); H@2"ove-uC
printf("e=0x%llx\n",a.e); Lr}b,
return 0; H(G^O&ppdB
} K
l0tyeT
结果: <+-Yh_D
24 P`3s\8[Q
c=0x0 -Xxu/U})%
d.a=0x504 Ei9_h
d.b=0x3020100 )y/DGSd
e=0x706050403020100 ]O7.ss/2
teOBsFy/I
H
MjeGO.i
网友 redleaves (ID最吊的网友)的答案和分析: &I}T<v{f
bxhg*A
如果代码: lKV\1(`
#pragma pack(8) h-b5
struct S1{ UrhM)h?%
char a; ,P@/=I5
long b; \n*7#aX/
}; U%^eIXV|
struct S2 { xjK_zO*dLq
char c; :e&n.i^
struct S1 d; "0'*q<8
long long e; Y1fy2\<'
}; Kl aZZJ
#pragma pack() ;naq-%'Sg
sizeof(S2)结果为24. Zc%foK{
成员对齐有一个重要的条件,即每个成员分别对齐.即每个成员按自己的方式对齐. .@i0U
也就是说上面虽然指定了按8字节对齐,但并不是所有的成员都是以8字节对齐.其对齐的规则是,每个成员按其类型的对齐参数(通常是这个类型的大小)和指定对齐参数(这里是8字节)中较小的一个对齐.并且结构的长度必须为所用过的所有对齐参数的整数倍,不够就补空字节. #6N+5Yx_[
LmXF`Y$
S1中,成员a是1字节默认按1字节对齐,指定对齐参数为8,这两个值中取1,a按1字节对齐;成员b是4个字节,默认是按4字节对齐,这时就按4字节对齐,所以sizeof(S1)应该为8; o=-Vt,2{
S2中,c和S1中的a一样,按1字节对齐,而d 是个结构,它是8个字节,它按什么对齐呢?对于结构来说,它的默认对齐方式就是它的所有成员使用的对齐参数中最大的一个,S1的就是4.所以,成员d就是按4字节对齐.成员e是8个字节,它是默认按8字节对齐,和指定的一样,所以它对到8字节的边界上,这时,已经使用了12个字节了,所以又添加了4个字节的空,从第16个字节开始放置成员e.这时,长度为24,已经可以被8(成员e按8字节对齐)整除.这样,一共使用了24个字节. A{aw<
P|+
a b J+71FP`ZH
S1的内存布局:11**,1111, >d{dZD}
c S1.a S1.b d hg?j)jl|
S2的内存布局:1***,11**,1111,****11111111 \]T=j#.S$
Hbjb7Y?[
这里有三点很重要: :WK"-v
1.每个成员分别按自己的方式对齐,并能最小化长度 zNV!@Yr
2.复杂类型(如结构)的默认对齐方式是它最长的成员的对齐方式,这样在成员是复杂类型时,可以最小化长度 ~_u*\]-
3.对齐后的长度必须是成员中最大的对齐参数的整数倍,这样在处理数组时可以保证每一项都边界对齐 QE45!Zg
/ojO>Y[<
TvunjTpaj
网友xue23(xue23) 的答案和分析: ([,vX"4
h"%|\o+3
有程序查一下各个变量的内存地址得知: ;-KAUgL2
各个变量在内存中的位置为 _{LN{iqDv
c***aa** n#+%!HTh
bbbb**** 3Q'[Ee2-3
dddddddd m]FaEQVoE
测试代码为: V#'26@@
s2 ss; eg"=H50
cout << "ss.c = " << &ss << endl ; 1R=)17'O
cout << "ss.d.a = " <<&ss.d.a << endl; eyeNrk*2o
cout << "ss.d.b = " <<&(ss.d.b) < cout << "ss.d = " <<&ss.e << endl; ~L %Pz0Gg
print out 各个变量的内存地址不就可以看出来了吗。 r}/yi
0'?V|V=v
所以答案是24,2. \{c,,th
4%g6_KB
但是我的想像中应该是这样的分布情况: FI]P<)*r
c******* W@I
02n2H
aa**bbbb hLb;5u&!kW
dddddddd 0a"igH}
-VS9`7k
不知为什么会c和a放在一起,组成8位长度。