Intel和微软同时出现的C语言面试题 B.dT)@Lx0
#pragma pack(8) O XP\R
I]`-|Q E
struct s1{ gVR@&bi7
short a; mY7>(M{
long b; qxOi>v0\H
}; [1yq{n=
0JjUAxNq
struct s2{ v6=-g$FG
char c; j2 %^qL
s1 d; \cJa;WM>
long long e; [<c&|tfl
}; Vu8,(A7D%O
!wz/cM;
#pragma pack() s>n(`?@L
9pKGr@ &
问 jeUUa-zR3
1.sizeof(s2) = ? aHzHvl
2.s2的s1中的a后面空了几个字节接着是b? b;cMl'
q(M:QWA q
<%?#AVU[
o4y']JSN
如果您知道答案请在讨论中写出,以下是部份网友的答案,供参考: p
*w$:L
eD?3"!c!
网友rwxybh(行云)的答案: @OpNHQat9
内存布局是 /0MDISQy9
1*** 11** G4 _,
1111 **** ?Bi*1V<R
1111 1111 z(y*hazK
"tk-w{>
所以答案就是24和3 "Zv~QwC
}f}}A=
下面是一个测试的程序,试一试就知道了,我用的是VC2005 %kshQ%P)?
~a9W3b4j
#pragma pack(8) T1WWK'
[{u(C!7L`
struct s1{ ?#A]{l
short a; // 2 BYtes LPd\-S_rsP
long b; // 4 Bytes Ol_q{^
}; w f.T3
struct s2{ J Yb}Zw;
char c; // 1 Byte dEa<g99[?
s1 d; // 8 Bytes 2BXy<BM @
long long e; // 8 Bytes m"eteA,"k_
}; )RgGcHT@
// 1*** 11** tz NlJ~E
// 1111 **** Q,T"Zd Q
// 1111 1111 O`1!
// Hh;:`;}
gY-5_Ab
// 00 01 02 03 04 05 06 07 w*9br SK
// 00 01 02 03 04 05 06 07 26?W
nu60
// 00 01 02 03 04 05 06 07 WiL2
// lCd@jB{
#pragma pack() }n:?7
>R,'5:Rw
int main(int argc, char* argv[]) _*M42<wcO
{ g`^X#-!(
s2 a; l\0w;:N3
char *p = (char *)&a; n"Veem[_4g
for(int i=0;i<24;++i) `mfq
2bVc
p = (char)(i%8); /UcV
printf("%d\n",sizeof(a)); iSLGwTdLn
printf("c=0x%lx\n",a.c); zw<p74DH
printf("d.a=0x%x\n",a.d.a); . 5y"38e
printf("d.b=0x%x\n",a.d.b); ZzGahtx)Y
printf("e=0x%llx\n",a.e); B;6]NCxD
return 0; ;h=*!7:
} E(pF:po
结果: {PU!=IkTS
24 )m3Uar
c=0x0 UB`ToE|Ii
d.a=0x504 3\O|ii
d.b=0x3020100 NH<gU_s8{9
e=0x706050403020100 ./vZe_o)j$
u|#>32kV
4LcX<BU9
网友 redleaves (ID最吊的网友)的答案和分析: lA(Q@yEW
/'2O.d0}.
如果代码: Wm~` ~P
#pragma pack(8) Dn9w@KO
struct S1{ %.v{N6
char a; DhLqhME53
long b; 85:NFa@J
}; N{SQ(%V
struct S2 { &.13dq
char c; MB
ju![n
struct S1 d; wFh8?Z3u_
long long e; }T^cEfX
}; Y}*\[}l:&x
#pragma pack() 'nQVj
sizeof(S2)结果为24. o{b=9-V
成员对齐有一个重要的条件,即每个成员分别对齐.即每个成员按自己的方式对齐. EJ}!F?o
也就是说上面虽然指定了按8字节对齐,但并不是所有的成员都是以8字节对齐.其对齐的规则是,每个成员按其类型的对齐参数(通常是这个类型的大小)和指定对齐参数(这里是8字节)中较小的一个对齐.并且结构的长度必须为所用过的所有对齐参数的整数倍,不够就补空字节. g>0XxjP4
1LJuCI=~
S1中,成员a是1字节默认按1字节对齐,指定对齐参数为8,这两个值中取1,a按1字节对齐;成员b是4个字节,默认是按4字节对齐,这时就按4字节对齐,所以sizeof(S1)应该为8; gJiK+&8I
S2中,c和S1中的a一样,按1字节对齐,而d 是个结构,它是8个字节,它按什么对齐呢?对于结构来说,它的默认对齐方式就是它的所有成员使用的对齐参数中最大的一个,S1的就是4.所以,成员d就是按4字节对齐.成员e是8个字节,它是默认按8字节对齐,和指定的一样,所以它对到8字节的边界上,这时,已经使用了12个字节了,所以又添加了4个字节的空,从第16个字节开始放置成员e.这时,长度为24,已经可以被8(成员e按8字节对齐)整除.这样,一共使用了24个字节. -$VZtex
a b ?^mi3VM
S1的内存布局:11**,1111, `nXVE+E@
c S1.a S1.b d <:FP4e
"(
S2的内存布局:1***,11**,1111,****11111111 c\6+=\
j:T/ iH!YF
这里有三点很重要: []R? ViG
1.每个成员分别按自己的方式对齐,并能最小化长度 o;a:Dd
2.复杂类型(如结构)的默认对齐方式是它最长的成员的对齐方式,这样在成员是复杂类型时,可以最小化长度 6Tw#^;q-
3.对齐后的长度必须是成员中最大的对齐参数的整数倍,这样在处理数组时可以保证每一项都边界对齐 =\#%j|9N9
{gA\ph%s
LTV{{Z+
网友xue23(xue23) 的答案和分析: }eQRN<}P
9//+Bh
有程序查一下各个变量的内存地址得知: W%2
80\h
各个变量在内存中的位置为 V=He_9B
c***aa** XY.5Rno4
bbbb**** @RFs/'
dddddddd >h2%[j=
测试代码为: uJHu>M}~
s2 ss; v[@c*wo
cout << "ss.c = " << &ss << endl ; 87)zCq
cout << "ss.d.a = " <<&ss.d.a << endl; /){KOCBl;
cout << "ss.d.b = " <<&(ss.d.b) < cout << "ss.d = " <<&ss.e << endl; ,oxcq?7#4
print out 各个变量的内存地址不就可以看出来了吗。 iqQUtE]E_
s5.AW8X=?*
所以答案是24,2. 5ercD
!MDNE*_
但是我的想像中应该是这样的分布情况: )D'^3)FF
c******* +MbIB&fRCB
aa**bbbb 'bGX-C
dddddddd > oA?6x
&Cim!I
不知为什么会c和a放在一起,组成8位长度。