Intel和微软同时出现的C语言面试题 bVOO)
#pragma pack(8) +2(PcJR~
YD+QX@
struct s1{ d.1Q~&`
short a; g[<uwknf
long b; ke</x+\F
}; |vN$"mp^a
"j;!_v>=f`
struct s2{ 73#9NZR
char c; {lKEZirO
s1 d; Oi#k:vq4
long long e; sp,(&Y]US
}; | &\^n2`>
{ r X5
#pragma pack() lMPbLF%_
Ua!Odju*w
问 F13%)G(
1.sizeof(s2) = ? <v-92?
2.s2的s1中的a后面空了几个字节接着是b? "lb\c
6!o/~I#
2X +7bM
$pJ3xp&
如果您知道答案请在讨论中写出,以下是部份网友的答案,供参考: lZ+/\s,]|
_4S7wOq5
网友rwxybh(行云)的答案: BC&^]M
内存布局是 n%Rjt!9
1*** 11** <m9JXO:5
1111 **** M%77u=m
1111 1111 M,Po54u
xKisL=l6Y
所以答案就是24和3 <#!8?o&i
s={X-H< 2
下面是一个测试的程序,试一试就知道了,我用的是VC2005
.;}pU!S~R
fY2l.H\f
#pragma pack(8) ;W =by2x*
3pzOt&T|w
struct s1{ _4De!q0(
short a; // 2 BYtes lHRK'?Q
long b; // 4 Bytes 0$(jBnE
}; 4>d[qr*<
struct s2{ A'w2GC{.
char c; // 1 Byte 5"]aZMua
s1 d; // 8 Bytes DOA[iT";4
long long e; // 8 Bytes HJ(=?TU
}; |O'Hh7
// 1*** 11** ec,z6v^9
// 1111 **** P}b Dn;
// 1111 1111 \>_eEZ5
// e1Dj0s?i~K
ZlUFJ*pk
// 00 01 02 03 04 05 06 07 ;%lJD"yF
// 00 01 02 03 04 05 06 07 FxMMxY,*%
// 00 01 02 03 04 05 06 07 S:DcfR=a
// + 4++Z
#pragma pack() d
u_O} x
7Co3P@@
int main(int argc, char* argv[]) 6YB-}>?
{ ~6=Wq64
s2 a; &7JEb]1C
char *p = (char *)&a; ">rsA&hN-
for(int i=0;i<24;++i) "1E?3PFJ
p = (char)(i%8); 3" 8t)s
printf("%d\n",sizeof(a)); F5Cqv0HV
printf("c=0x%lx\n",a.c); %YsRm%q
printf("d.a=0x%x\n",a.d.a); GWVEIZ
printf("d.b=0x%x\n",a.d.b); qsQ]M^@>
printf("e=0x%llx\n",a.e); :a#|
return 0; #zh6=.,7
} |2tSUOZ
结果: S;G"L$&\
24 75' Ua$
c=0x0 *(>F'>F1"
d.a=0x504 8yNRxiW:
d.b=0x3020100 B>c[Zg1
e=0x706050403020100 IhtmD@H}
4"`=hu Q
GA}hp%
网友 redleaves (ID最吊的网友)的答案和分析: ' h0\4eu
/6?tgr
如果代码: eU<]h>2
#pragma pack(8) Vu^Q4Z
struct S1{ 2*b#+ b
char a; !^rITiy
long b; UzP@{?
}; :"h
Pg]'
struct S2 { .CB"@.7
char c; LD7? .
struct S1 d; G=+!d&mbg
long long e; R|d^M&K,
}; hA$c.jJr.Z
#pragma pack() Vw6>:l<+<
sizeof(S2)结果为24. j=zU7wz)D
成员对齐有一个重要的条件,即每个成员分别对齐.即每个成员按自己的方式对齐. y81#UD9[
也就是说上面虽然指定了按8字节对齐,但并不是所有的成员都是以8字节对齐.其对齐的规则是,每个成员按其类型的对齐参数(通常是这个类型的大小)和指定对齐参数(这里是8字节)中较小的一个对齐.并且结构的长度必须为所用过的所有对齐参数的整数倍,不够就补空字节. 6tCV{pgm
{3_F fsg`
S1中,成员a是1字节默认按1字节对齐,指定对齐参数为8,这两个值中取1,a按1字节对齐;成员b是4个字节,默认是按4字节对齐,这时就按4字节对齐,所以sizeof(S1)应该为8; AiR%MD
S2中,c和S1中的a一样,按1字节对齐,而d 是个结构,它是8个字节,它按什么对齐呢?对于结构来说,它的默认对齐方式就是它的所有成员使用的对齐参数中最大的一个,S1的就是4.所以,成员d就是按4字节对齐.成员e是8个字节,它是默认按8字节对齐,和指定的一样,所以它对到8字节的边界上,这时,已经使用了12个字节了,所以又添加了4个字节的空,从第16个字节开始放置成员e.这时,长度为24,已经可以被8(成员e按8字节对齐)整除.这样,一共使用了24个字节. c9>8IW
a b E0WrpGZ
S1的内存布局:11**,1111, u k>q\j
c S1.a S1.b d KR+ aY.
S2的内存布局:1***,11**,1111,****11111111 4C2>0O<^s
@Wlwt+;fT
这里有三点很重要: }Etd#">
1.每个成员分别按自己的方式对齐,并能最小化长度 aH~x7N6!
2.复杂类型(如结构)的默认对齐方式是它最长的成员的对齐方式,这样在成员是复杂类型时,可以最小化长度 Z &ua,:5
3.对齐后的长度必须是成员中最大的对齐参数的整数倍,这样在处理数组时可以保证每一项都边界对齐 0D W'(#`
e%5'(V-y,
\ZmFH8=|f
网友xue23(xue23) 的答案和分析: ^Hy)<P
?kG#qt]Q5
有程序查一下各个变量的内存地址得知: AOq9v~)z-
各个变量在内存中的位置为 3:z4M9f
c***aa** U[H+87zg
bbbb**** N69eIdl
dddddddd "m<eHz]D
测试代码为: FN8=YUYK%
s2 ss; pEqr0Qwh
cout << "ss.c = " << &ss << endl ; PAO[Og,-
cout << "ss.d.a = " <<&ss.d.a << endl; H@OrX
cout << "ss.d.b = " <<&(ss.d.b) < cout << "ss.d = " <<&ss.e << endl; 8=u+BDG
print out 各个变量的内存地址不就可以看出来了吗。 rA>A=,
fS'k;r*r
所以答案是24,2. )U3 H15
@8x6#|D
但是我的想像中应该是这样的分布情况: 3e!a>Gl*
c******* 6kmZ!9w0|
aa**bbbb JXD?a.vy^q
dddddddd $TH'"XK
O_%PBgcJr
不知为什么会c和a放在一起,组成8位长度。