Intel和微软同时出现的C语言面试题 '8v^.gZ
#pragma pack(8) \4`~J@5Y
#$QC2;/)F
struct s1{ >v9 ("
short a; < 6[XE
long b; l Ud/^u`
}; Ms. 1RCup
wPYz&&W
struct s2{ t%wC~1
char c; vJT
%ET
s1 d; G-[fz
long long e; z )2h\S
}; {(i>$RG_
%SL'X`j
#pragma pack() cbD&tsF
N*N@wJy:5
问 s('<ms
1.sizeof(s2) = ? cWSiJr):r
2.s2的s1中的a后面空了几个字节接着是b? ~r6qnC2
Tp&03
E4aCL#}D
oX@0+*"
如果您知道答案请在讨论中写出,以下是部份网友的答案,供参考: QXnL(z
6u`E{$
网友rwxybh(行云)的答案: EM+#h'%-
内存布局是 L<encPJt
1*** 11** r<38; a
1111 **** 7yLO<o?9w
1111 1111 j_VTa/
_Kg:jal
所以答案就是24和3 mr]IxTv
+(*S@V$c
下面是一个测试的程序,试一试就知道了,我用的是VC2005 ;#G)([
-(4)lw>U
#pragma pack(8) 445}Yw5;9
Cvr?%+)$M
struct s1{ q$Z.5EN
short a; // 2 BYtes ,lLkAd?q
long b; // 4 Bytes V8w!yc
}; 1H{M0e
struct s2{ 6H,n?[zTt
char c; // 1 Byte L,L>cmpM
s1 d; // 8 Bytes wiXdb[[#
long long e; // 8 Bytes )54;YK
}; e#MEDjm/)g
// 1*** 11** )'BuRN8
// 1111 **** c0.i
// 1111 1111 fJ_d,4
// ;ZMm6o
s+;J`_M
// 00 01 02 03 04 05 06 07 l(Dkmt>^
// 00 01 02 03 04 05 06 07 a%a_sR\)
// 00 01 02 03 04 05 06 07 %y{#fZHc
// =Jd('r
#pragma pack() 3VZeUOxY\W
s*.CJ
int main(int argc, char* argv[]) Z?yMy zT
{ qi7(RL_N
s2 a; rnvKfTpZDU
char *p = (char *)&a; &L[7jA'[J
for(int i=0;i<24;++i) ?YzOA${
p = (char)(i%8); rcUXYJCh-
printf("%d\n",sizeof(a)); 5(0f"zY
printf("c=0x%lx\n",a.c); (he cvJ
printf("d.a=0x%x\n",a.d.a); zyyt`
printf("d.b=0x%x\n",a.d.b); $Cw>
z^}u
printf("e=0x%llx\n",a.e); !e?g"5r{Bv
return 0; t{n|!T&
} D7.|UG?G
结果: 6 KuB<od
24 4<b=;8
c=0x0 SXfuPM
d.a=0x504 Te=[tx~x
d.b=0x3020100 e|)6zh<O:
e=0x706050403020100 >CtT_yhx
:=q blc
$Fx:w
网友 redleaves (ID最吊的网友)的答案和分析: :r%Hsur(
^sz4-+>
如果代码: B]Vnu7
#pragma pack(8) LWQ.!;HY p
struct S1{ [jb3lO$Xa
char a; G9y
0;br
long b; k*)O]M<,
}; $I40 hk
struct S2 { ]PQ] f*Ik>
char c; n\8;4]n
struct S1 d; 0'T*l2Z`2
long long e; gFR9!=,/V%
}; AnK-\4
#pragma pack() 5g9lO]WDI
sizeof(S2)结果为24. W`HO Q
成员对齐有一个重要的条件,即每个成员分别对齐.即每个成员按自己的方式对齐. oG5:]/F
也就是说上面虽然指定了按8字节对齐,但并不是所有的成员都是以8字节对齐.其对齐的规则是,每个成员按其类型的对齐参数(通常是这个类型的大小)和指定对齐参数(这里是8字节)中较小的一个对齐.并且结构的长度必须为所用过的所有对齐参数的整数倍,不够就补空字节. C{mL]ds<
tHlKo0S$0
S1中,成员a是1字节默认按1字节对齐,指定对齐参数为8,这两个值中取1,a按1字节对齐;成员b是4个字节,默认是按4字节对齐,这时就按4字节对齐,所以sizeof(S1)应该为8; 4 [2^#t[
S2中,c和S1中的a一样,按1字节对齐,而d 是个结构,它是8个字节,它按什么对齐呢?对于结构来说,它的默认对齐方式就是它的所有成员使用的对齐参数中最大的一个,S1的就是4.所以,成员d就是按4字节对齐.成员e是8个字节,它是默认按8字节对齐,和指定的一样,所以它对到8字节的边界上,这时,已经使用了12个字节了,所以又添加了4个字节的空,从第16个字节开始放置成员e.这时,长度为24,已经可以被8(成员e按8字节对齐)整除.这样,一共使用了24个字节. R%)ZhG*
a b 6[g~p< 8n}
S1的内存布局:11**,1111, XRi/O)98o
c S1.a S1.b d P70\ |M0~y
S2的内存布局:1***,11**,1111,****11111111 ?;1^8 c0
\LX!n!@
这里有三点很重要: )c
vA}U.z
1.每个成员分别按自己的方式对齐,并能最小化长度 M{ #
2.复杂类型(如结构)的默认对齐方式是它最长的成员的对齐方式,这样在成员是复杂类型时,可以最小化长度 LgN\%5f-
3.对齐后的长度必须是成员中最大的对齐参数的整数倍,这样在处理数组时可以保证每一项都边界对齐 !vNZ-}
L'XX++2
nO{@p_3mi
网友xue23(xue23) 的答案和分析: Wez"E2J`
6*3J3Lc_<
有程序查一下各个变量的内存地址得知: ^+Ho#]
各个变量在内存中的位置为 W\xM$#)m
c***aa** ,VK! 3$;|
bbbb**** Ul@Jg
dddddddd '\yp}r'u
测试代码为: 0Y7b$~n'Y
s2 ss; VO"f=gFg
cout << "ss.c = " << &ss << endl ; WR'm<u
cout << "ss.d.a = " <<&ss.d.a << endl; r?Y+TtF\e
cout << "ss.d.b = " <<&(ss.d.b) < cout << "ss.d = " <<&ss.e << endl; 3m1]Ia-9
print out 各个变量的内存地址不就可以看出来了吗。 ~9#nC`%2j
#P:o
所以答案是24,2. |)'gQvDM
a o_A%?Ld
但是我的想像中应该是这样的分布情况: QIl![%
c******* '^Kmfc
aa**bbbb " jefB6k9h
dddddddd -cW`qWbd
!Gwf"-TQ
不知为什么会c和a放在一起,组成8位长度。