Intel和微软同时出现的C语言面试题 3-tp94`8}t
#pragma pack(8) H=7dp%b"
tz._*n83
struct s1{ CuU"s)
short a; ^#XxqVdPk
long b; ;I]TM#qGF
}; Hm1C|Qb
d$b{KyUA
struct s2{ Yb414 K
char c; 'j>^L
s1 d; 90teXxg=|
long long e; {/ZB>l@D>8
}; cXtL3T+
69\0$O
#pragma pack() ! =I:Uc-Y
pO=bcs8Z
问 0nG&
LL5
1.sizeof(s2) = ? I0GL/a4s
2.s2的s1中的a后面空了几个字节接着是b? Y"G$^3% (]
nvgo6*
Sr%~
5Q[W
Ow+7o@$"/
如果您知道答案请在讨论中写出,以下是部份网友的答案,供参考: ]X@/0
wf<uG|90
网友rwxybh(行云)的答案: {I`B?6K5
内存布局是 Iu%/~FgPj{
1*** 11** ApjLY58=
1111 ****
X!nI{PE
1111 1111 [Zi\L>PHO
vqv(KsD+::
所以答案就是24和3 >PL/>
`hI1
下面是一个测试的程序,试一试就知道了,我用的是VC2005 st'Y j
ZVgR7+`]#
#pragma pack(8) 5as';1^P&*
HwM:bY
N
struct s1{ >/
HC{.k
short a; // 2 BYtes (f
$Y0;v>}
long b; // 4 Bytes L.ndLd
}; DpI_`TF#$Z
struct s2{ s^js}9]p
char c; // 1 Byte 9]7+fu
s1 d; // 8 Bytes DEqk9Exk`
long long e; // 8 Bytes _17c}o#`5w
}; (Q#ArMMORI
// 1*** 11** vWjK[5
M%
// 1111 **** bbA+ZLZJn
// 1111 1111 _ 4Hf?m7z
// S3btx9y{
LP#CA^*S
// 00 01 02 03 04 05 06 07 8t0i
j
// 00 01 02 03 04 05 06 07 rS)7D
// 00 01 02 03 04 05 06 07 w.^k':,"
// z&cfFx#h)
#pragma pack() r 3pfG
wp.'M?6`L
int main(int argc, char* argv[]) B=|yjA'Fg
{ tAbIT;>
s2 a; -D38>#Y
char *p = (char *)&a; /xj'Pq((}p
for(int i=0;i<24;++i) y)Ip\.KV\
p = (char)(i%8); E5-8tHV
printf("%d\n",sizeof(a)); r(%#@?&
printf("c=0x%lx\n",a.c); ax7ub
printf("d.a=0x%x\n",a.d.a); ft:/-$&H
printf("d.b=0x%x\n",a.d.b); WNlWigwYl
printf("e=0x%llx\n",a.e); LPewo AXO
return 0; hFylQfd
} "R4~
8 r
结果: $N:m
9R
24 8Bo'0
c=0x0 nLdI>c9R
d.a=0x504 in(n[K
d.b=0x3020100 P8z++h
e=0x706050403020100 c\]h YKA
89+m?H]K
9FH=Jp
网友 redleaves (ID最吊的网友)的答案和分析: 93[`1_q7\
LOR$d^l
如果代码: ^Q2K0'm5
#pragma pack(8) ?HZ+fS,-
struct S1{ :%!=Ej.J
char a; )k0bP1oGS
long b; /HI#8
}; SYa!IL-B
struct S2 { 2R:['QT
char c; _EjS(.e/=
struct S1 d; /`:5#O
long long e; O:p~L`o>>
}; AkT_ZU>
#pragma pack() m'z <d
sizeof(S2)结果为24. +% '0;
成员对齐有一个重要的条件,即每个成员分别对齐.即每个成员按自己的方式对齐. g&riio7lx
也就是说上面虽然指定了按8字节对齐,但并不是所有的成员都是以8字节对齐.其对齐的规则是,每个成员按其类型的对齐参数(通常是这个类型的大小)和指定对齐参数(这里是8字节)中较小的一个对齐.并且结构的长度必须为所用过的所有对齐参数的整数倍,不够就补空字节. T~`m'4"+c
tUz!]P2BUO
S1中,成员a是1字节默认按1字节对齐,指定对齐参数为8,这两个值中取1,a按1字节对齐;成员b是4个字节,默认是按4字节对齐,这时就按4字节对齐,所以sizeof(S1)应该为8; vHJ ~~if
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|?2 @VE
a b [eG- &u
S1的内存布局:11**,1111, e?RHf_d3T-
c S1.a S1.b d
1u)I}"{W>
S2的内存布局:1***,11**,1111,****11111111 b3y@!_'c
]*I&104{
这里有三点很重要: QP[w{T
1.每个成员分别按自己的方式对齐,并能最小化长度 =Lp0i9c
2.复杂类型(如结构)的默认对齐方式是它最长的成员的对齐方式,这样在成员是复杂类型时,可以最小化长度 wR>\5z)^
3.对齐后的长度必须是成员中最大的对齐参数的整数倍,这样在处理数组时可以保证每一项都边界对齐 b`18y cVME
i#(T?=VPcy
[$-y8`~(
网友xue23(xue23) 的答案和分析: zx0{cNPK5
rf^1%Zo:
有程序查一下各个变量的内存地址得知: 19;\:tN
各个变量在内存中的位置为 b.j\=c
c***aa** qo$<&'r
bbbb**** nyTfTn
dddddddd Ql
[=
测试代码为: 1w1(FpQO.
s2 ss; )CihqsA2
cout << "ss.c = " << &ss << endl ; [A[vR7&S
cout << "ss.d.a = " <<&ss.d.a << endl; nJA\P1@m
cout << "ss.d.b = " <<&(ss.d.b) < cout << "ss.d = " <<&ss.e << endl; U2@?!B[\d`
print out 各个变量的内存地址不就可以看出来了吗。
`6Y'H2WJ?
"m/0>UU0
所以答案是24,2. 9dSKlB5J
+}X@{DB
但是我的想像中应该是这样的分布情况: 2l8jw:=H
c******* M)Ogb'@#
aa**bbbb 0&c12W|B<L
dddddddd d}ue/hdw
@ ;rU#
不知为什么会c和a放在一起,组成8位长度。