Intel和微软同时出现的C语言面试题 ao!r6:&v$e
#pragma pack(8) #rwR)9iC0
,d+mT^jN
struct s1{ [8w2U%}]
short a; YB|9k)Z2[
long b; K&h6#[^\d
}; ihVQ,Cth
=!X4j3Cv
struct s2{ ZIp=JR8o$
char c; EUkNh>U?
s1 d; =)8Ct
long long e; 68*{Lo?U
}; _;{-w%Vf
qg/5m;U
#pragma pack() gib]#n1!p
z"#.o^5
问 !)=o,sVA
1.sizeof(s2) = ? CmOb+:4@K
2.s2的s1中的a后面空了几个字节接着是b? @gc"-V*-/
EoeEg,'~F
EiUV?Gvz
`N|CL
如果您知道答案请在讨论中写出,以下是部份网友的答案,供参考: `^kST><
?r<F\rBT7*
网友rwxybh(行云)的答案: %"zJsYQ!
内存布局是 Ev16xL8B
1*** 11** wrU[#g,uvr
1111 **** -wfV
1111 1111 *zWn4BckN
'r%oOZk)z
所以答案就是24和3 @\?f77Of6
+IYSWR
下面是一个测试的程序,试一试就知道了,我用的是VC2005 sh2bhv]
^@2Vh*k
#pragma pack(8) #Au&2_O
b*KZe[#M1
struct s1{ W\7*T1TDj
short a; // 2 BYtes v_0!uT5~NE
long b; // 4 Bytes KoJG!Rm
}; r
`dU
(T!
struct s2{ -huZnDN
char c; // 1 Byte *
U4:K@y
s1 d; // 8 Bytes sBnPS[Oo
long long e; // 8 Bytes *lAdS]I
}; <*(R+to^d
// 1*** 11** @`D6F;R
// 1111 **** lv*uXg.k^
// 1111 1111 9,CC1f
// P;&p[[7
N~jQ!y
// 00 01 02 03 04 05 06 07 p%1m&/`F
// 00 01 02 03 04 05 06 07 [!mjUsut*
// 00 01 02 03 04 05 06 07 1.uQ(>n
// su;S)yZb
#pragma pack() ;7k7/f:
>>zoG3H!
int main(int argc, char* argv[]) RzQS@^u*F0
{ QO k"UP
s2 a; em}Qv3*#
char *p = (char *)&a; iGLYM-
for(int i=0;i<24;++i) c&-$?f
r
p = (char)(i%8); {2r7:nvR
printf("%d\n",sizeof(a)); P*Sip?tdE
printf("c=0x%lx\n",a.c); |81N/]EER
printf("d.a=0x%x\n",a.d.a); 6~WE#z_
printf("d.b=0x%x\n",a.d.b); o q)"1
printf("e=0x%llx\n",a.e); V&v~kzLr+
return 0; W2qQKv
} w lg#c6#q
结果: QL18MbfqP
24 )fc"])&8
c=0x0 :w%bw\}
d.a=0x504 bU`yymf{L
d.b=0x3020100 {+9\o ~
e=0x706050403020100 n9!3h ?,g
98'XSL|
%0]b5u
网友 redleaves (ID最吊的网友)的答案和分析: [_b='/8
g}QTZT8
如果代码: I>Fh*2
#pragma pack(8) a&Du5(r;!
struct S1{ 5O
;^Mk|
char a; z %E!tB2o
long b; C&N4<2b
}; s,H(m8#>
struct S2 { {NgY8wQB
char c; \3?;[xD
struct S1 d; gEHfsR=D6
long long e; ArzsZ<\//
}; d ovwB`5
#pragma pack() JBAK*g
sizeof(S2)结果为24. XYF~Q9~
成员对齐有一个重要的条件,即每个成员分别对齐.即每个成员按自己的方式对齐. VQMd[/
也就是说上面虽然指定了按8字节对齐,但并不是所有的成员都是以8字节对齐.其对齐的规则是,每个成员按其类型的对齐参数(通常是这个类型的大小)和指定对齐参数(这里是8字节)中较小的一个对齐.并且结构的长度必须为所用过的所有对齐参数的整数倍,不够就补空字节. }A/&]1GWk
6F/
OlK<
S1中,成员a是1字节默认按1字节对齐,指定对齐参数为8,这两个值中取1,a按1字节对齐;成员b是4个字节,默认是按4字节对齐,这时就按4字节对齐,所以sizeof(S1)应该为8; jYID44$
S2中,c和S1中的a一样,按1字节对齐,而d 是个结构,它是8个字节,它按什么对齐呢?对于结构来说,它的默认对齐方式就是它的所有成员使用的对齐参数中最大的一个,S1的就是4.所以,成员d就是按4字节对齐.成员e是8个字节,它是默认按8字节对齐,和指定的一样,所以它对到8字节的边界上,这时,已经使用了12个字节了,所以又添加了4个字节的空,从第16个字节开始放置成员e.这时,长度为24,已经可以被8(成员e按8字节对齐)整除.这样,一共使用了24个字节. yc=#Jn?S
a b q<[ke
S1的内存布局:11**,1111, <SdJM1%Qo
c S1.a S1.b d .eB"la|d
S2的内存布局:1***,11**,1111,****11111111 W;]UP$5l
FKnQwX.0
这里有三点很重要: <D;Q8
1.每个成员分别按自己的方式对齐,并能最小化长度 bu]Se6%}
2.复杂类型(如结构)的默认对齐方式是它最长的成员的对齐方式,这样在成员是复杂类型时,可以最小化长度 SliQwm5
3.对齐后的长度必须是成员中最大的对齐参数的整数倍,这样在处理数组时可以保证每一项都边界对齐 -G#@BtB2+
iiB )/~!O
^i)Q
CDU7
网友xue23(xue23) 的答案和分析: '4lT*KN7\
wf<`J/7u
有程序查一下各个变量的内存地址得知: yPG\ &Bo
各个变量在内存中的位置为 }.V0SM6
c***aa** >@"3Q`
bbbb**** IYg3ve`x
dddddddd TxxB0
测试代码为: nk$V{(FJ
s2 ss; o+Ti$`2<O7
cout << "ss.c = " << &ss << endl ; ur,"K'w
cout << "ss.d.a = " <<&ss.d.a << endl; bTy)0ta>AF
cout << "ss.d.b = " <<&(ss.d.b) < cout << "ss.d = " <<&ss.e << endl; f<4q ]HCa
print out 各个变量的内存地址不就可以看出来了吗。 )X!DCL:16
| 4oM+n;Y
所以答案是24,2. J~'Q^O3@
(g2r\hI
但是我的想像中应该是这样的分布情况: NF(IF.8G
c******* XAxI?y[c
aa**bbbb )/T$H|
dddddddd S Y>,kwHO
@TPgA(5NR
不知为什么会c和a放在一起,组成8位长度。