Intel和微软同时出现的C语言面试题 JVvs-bK5
#pragma pack(8) 1H?
u Qy
5sj4;w[
struct s1{ x-WmMfcz&
short a; }7|1
long b; n9W(bG o
}; KrgFKRgGj
[+2[`K
c]
struct s2{ ,1~"eGl!
char c; [M]
s1 d; BTqS'NuT
long long e; X9v.1s,
}; TaZmRL
q6McG HT
#pragma pack() 2J7:\pR^
q<xCb%#Jl
问 | k&Ck
1.sizeof(s2) = ? !,wIQy_e4
2.s2的s1中的a后面空了几个字节接着是b? $O&b``
~Z\8UsVN
DrKP%BnS
\pa"%c)
如果您知道答案请在讨论中写出,以下是部份网友的答案,供参考: <Th6r.#?
gh/EU/~d
网友rwxybh(行云)的答案: jD$,.AVvz
内存布局是 "0"nw2g?
1*** 11** dN$0OS`s[
1111 **** !j9t*2m[
1111 1111 G,&<<2{(f;
[^WC lRF
所以答案就是24和3 B~1_ 28\
K0u|U`
下面是一个测试的程序,试一试就知道了,我用的是VC2005 !a{^=#qq&I
m~iXl,r
#pragma pack(8) qzYwt]GNS
"3X2VFwoJ
struct s1{ Lu?C-$a C
short a; // 2 BYtes jZu[n)u'C
long b; // 4 Bytes Y+kfBvxyf
}; qk%;on&`
struct s2{ ;,hwZZA
char c; // 1 Byte `LrHKb
aP
s1 d; // 8 Bytes Q1U\D
long long e; // 8 Bytes 2]z8:a
}; bZ dNibN
// 1*** 11** ]Z>}6!
// 1111 **** 8V~k5#&Ow
// 1111 1111 k9<;woOBO
// .iYJr;9`d
}fp-pe69z
// 00 01 02 03 04 05 06 07 _('=b/
// 00 01 02 03 04 05 06 07 BOX{]EOj
// 00 01 02 03 04 05 06 07 ~k"=4j9
// 4zXFuTr($
#pragma pack() Me r/G2#&
e6`Jbu+J<f
int main(int argc, char* argv[]) *l"T$H
{ S.mG?zbw
s2 a; 4R#chQ
char *p = (char *)&a; DEBB()6,
for(int i=0;i<24;++i) RF`.xQ26=
p = (char)(i%8); 6O7'!@@
printf("%d\n",sizeof(a)); WltQ63u
printf("c=0x%lx\n",a.c); 4svBzZdr
printf("d.a=0x%x\n",a.d.a); >f|||H}Snw
printf("d.b=0x%x\n",a.d.b);
"0V.V>-p
printf("e=0x%llx\n",a.e); |.(dq^
return 0; '3R`lv
} ;nI] !g:
结果: M-$%Rzl_
24 ^a/gBC82x
c=0x0 e|g5=2(Pr&
d.a=0x504 (j%~u&+-
d.b=0x3020100 M=8.Bp|Ye
e=0x706050403020100 )1Y{Q Y}l
jrCfWa}z
kYM~d07 V
网友 redleaves (ID最吊的网友)的答案和分析: Rm2yPuOU}A
%p Ynnfr
如果代码: tl[Uw[
#pragma pack(8) N,<uf@LQ
struct S1{ ZAW^/bo<
char a; FDv<\2+ c
long b; H/"-Z;0{
}; hE &xE;
struct S2 { S~<$Hy*kh
char c; g6yB6vk
struct S1 d; 'HO$C,1]
long long e; ww)<E`eGi
}; 'Y?"{HZ
#pragma pack() ~b(i&DVK
sizeof(S2)结果为24. |+{)_?
成员对齐有一个重要的条件,即每个成员分别对齐.即每个成员按自己的方式对齐. <NHH^M\N
也就是说上面虽然指定了按8字节对齐,但并不是所有的成员都是以8字节对齐.其对齐的规则是,每个成员按其类型的对齐参数(通常是这个类型的大小)和指定对齐参数(这里是8字节)中较小的一个对齐.并且结构的长度必须为所用过的所有对齐参数的整数倍,不够就补空字节. W1WYej"
FX;QG94!
S1中,成员a是1字节默认按1字节对齐,指定对齐参数为8,这两个值中取1,a按1字节对齐;成员b是4个字节,默认是按4字节对齐,这时就按4字节对齐,所以sizeof(S1)应该为8; a f6M,{F
S2中,c和S1中的a一样,按1字节对齐,而d 是个结构,它是8个字节,它按什么对齐呢?对于结构来说,它的默认对齐方式就是它的所有成员使用的对齐参数中最大的一个,S1的就是4.所以,成员d就是按4字节对齐.成员e是8个字节,它是默认按8字节对齐,和指定的一样,所以它对到8字节的边界上,这时,已经使用了12个字节了,所以又添加了4个字节的空,从第16个字节开始放置成员e.这时,长度为24,已经可以被8(成员e按8字节对齐)整除.这样,一共使用了24个字节. 3_C|z,\:
a b hl;u'_AB
S1的内存布局:11**,1111, /hpY f]t
c S1.a S1.b d ?)/#+[xa
S2的内存布局:1***,11**,1111,****11111111 hz{`h
+[Dx?XM
这里有三点很重要: f<-Jg
1.每个成员分别按自己的方式对齐,并能最小化长度 oxr#7Ei0d
2.复杂类型(如结构)的默认对齐方式是它最长的成员的对齐方式,这样在成员是复杂类型时,可以最小化长度 BIH-"vTy
3.对齐后的长度必须是成员中最大的对齐参数的整数倍,这样在处理数组时可以保证每一项都边界对齐 q~rEq%tk
]GUvV&6@(
]z;P9B3@&
网友xue23(xue23) 的答案和分析: %Wg'i!?cB
"x%Htq@
有程序查一下各个变量的内存地址得知: )z>|4@,
各个变量在内存中的位置为 SP@ >vl+;
c***aa** .28<tEf
bbbb**** 5b5x!do
dddddddd f0!))/rSD
测试代码为: {GvJZ!,RCg
s2 ss; 6o^,@~:R
cout << "ss.c = " << &ss << endl ; Cwr~HY
cout << "ss.d.a = " <<&ss.d.a << endl; /{Is0+)
cout << "ss.d.b = " <<&(ss.d.b) < cout << "ss.d = " <<&ss.e << endl; C^s^D:
print out 各个变量的内存地址不就可以看出来了吗。 uMUBh 80,L
y+Ra4G#/}
所以答案是24,2. r+' qd)
XWDL5K
但是我的想像中应该是这样的分布情况: ~Cbc<[}
c******* a@8v^G
aa**bbbb Qd)q([
dddddddd #akpXdXs
"Hya6k>j
不知为什么会c和a放在一起,组成8位长度。