Intel和微软同时出现的C语言面试题 U)]natB
#pragma pack(8) :FpBz~!a
; 2-kQK9
struct s1{ u$p|hd
d
short a; &7u
Ra1/R
long b; geSo#mV
}; Ao0PFY
T-i]O*u
struct s2{ Jc^ozw
char c; 4!%LD(jB`B
s1 d; 31Mc<4zI8
long long e; eW,Pn'
}; 5B/\vLHg4
08jQq#
#pragma pack() ;#yz i2f
)!-'S H
问 'qS!n
1.sizeof(s2) = ? .tsB$,/
2.s2的s1中的a后面空了几个字节接着是b? nDw9
1V?)zp
C YKGf1;If
@sO.g_yM
如果您知道答案请在讨论中写出,以下是部份网友的答案,供参考: 7gaC)j&
/*HSAjv
网友rwxybh(行云)的答案: !Sh5o'D28
内存布局是 h1)\.F4G
1*** 11** `2
1111 **** +t{FF!mL
1111 1111 %&(\dt&R1h
i.4[]f[/h
所以答案就是24和3 y-k-E/V}
$dw;Kj'\
下面是一个测试的程序,试一试就知道了,我用的是VC2005 o!S_j^p[C
T/5UlW|\
#pragma pack(8) -. {7;6:(k
a9Rh
struct s1{ SoIMf tX
short a; // 2 BYtes M
-TK
long b; // 4 Bytes P'k39
}; A79SAheX#
struct s2{ UU`qI}Ys8F
char c; // 1 Byte 8+F2
!IM
s1 d; // 8 Bytes 0AenDm@9
long long e; // 8 Bytes e(A&VIp
}; g'E^@1{
// 1*** 11** PeaD]
// 1111 **** 4R6 .GO
// 1111 1111 rD?o97
// rtz(Jt{<
7lu;lAAP
// 00 01 02 03 04 05 06 07 tvILLR
// 00 01 02 03 04 05 06 07 v<4zcMv
// 00 01 02 03 04 05 06 07 '#?hm-Ga
// ERplDSfO-
#pragma pack() F{Hy@7
lom4z\6
int main(int argc, char* argv[]) (ol 3vt
{ 9AaixI
s2 a; 9UX-)!
char *p = (char *)&a; ?jnEHn
for(int i=0;i<24;++i) on|>"F`pb
p = (char)(i%8); M Cz3RZK
printf("%d\n",sizeof(a)); Sob+l'U$
printf("c=0x%lx\n",a.c); K\PS$
printf("d.a=0x%x\n",a.d.a); 7 m%|TwJN
printf("d.b=0x%x\n",a.d.b); 4" @yGXUb
printf("e=0x%llx\n",a.e); 1Cthi[B
return 0; ~mU#u\r(*
} 6}0#({s:R
结果: Q_S
fFsY
24 h2y@xnn
c=0x0 (RF6K6~
d.a=0x504 3[$VW+YV
d.b=0x3020100 4*]`s|fbu
e=0x706050403020100 [z?XVl<
R?k1)n
Cv3H%g+as
网友 redleaves (ID最吊的网友)的答案和分析: =y
ff.3mW\
%pdfGM9g
如果代码: 4YJs4CB
#pragma pack(8) f|EWu
struct S1{ b^ZrevM
char a; KMv|;yXYj4
long b; /<5/gV 1Q
}; wTLHg2'y^
struct S2 { &c'unKH
char c; =+u$ZZ0+]o
struct S1 d; HV>W f"1
long long e; k0,~wn\#h
}; ,PnEDQ|l
#pragma pack() GlaWBF#
sizeof(S2)结果为24. }9'rTLM
成员对齐有一个重要的条件,即每个成员分别对齐.即每个成员按自己的方式对齐. ky*-_
也就是说上面虽然指定了按8字节对齐,但并不是所有的成员都是以8字节对齐.其对齐的规则是,每个成员按其类型的对齐参数(通常是这个类型的大小)和指定对齐参数(这里是8字节)中较小的一个对齐.并且结构的长度必须为所用过的所有对齐参数的整数倍,不够就补空字节. E+_}8J .
I".r`$XZ
S1中,成员a是1字节默认按1字节对齐,指定对齐参数为8,这两个值中取1,a按1字节对齐;成员b是4个字节,默认是按4字节对齐,这时就按4字节对齐,所以sizeof(S1)应该为8; WW&0FugY_
S2中,c和S1中的a一样,按1字节对齐,而d 是个结构,它是8个字节,它按什么对齐呢?对于结构来说,它的默认对齐方式就是它的所有成员使用的对齐参数中最大的一个,S1的就是4.所以,成员d就是按4字节对齐.成员e是8个字节,它是默认按8字节对齐,和指定的一样,所以它对到8字节的边界上,这时,已经使用了12个字节了,所以又添加了4个字节的空,从第16个字节开始放置成员e.这时,长度为24,已经可以被8(成员e按8字节对齐)整除.这样,一共使用了24个字节. h0!j ;fn
a b >q}EZC
S1的内存布局:11**,1111, n'&WIf3
c S1.a S1.b d FT=w`NE,+
S2的内存布局:1***,11**,1111,****11111111 _)ERi*}x8
TJCoID7a8
这里有三点很重要: B^oXUEOImq
1.每个成员分别按自己的方式对齐,并能最小化长度 PR Y)hb;1
2.复杂类型(如结构)的默认对齐方式是它最长的成员的对齐方式,这样在成员是复杂类型时,可以最小化长度 g{&ux k);
3.对齐后的长度必须是成员中最大的对齐参数的整数倍,这样在处理数组时可以保证每一项都边界对齐 sI`Lsd'V
h><;TAp
>:s:`Au
网友xue23(xue23) 的答案和分析: &9'6hMu
upWq=_
有程序查一下各个变量的内存地址得知: z\v\T|C
各个变量在内存中的位置为 E*[X\70
c***aa** LJT+tb?K
bbbb**** S\Q/ "Y
dddddddd hhwV)Z
测试代码为: " #JRw
s2 ss; f9!wO';P6
cout << "ss.c = " << &ss << endl ; )@Ly{cw
cout << "ss.d.a = " <<&ss.d.a << endl; >RRb8=[J
cout << "ss.d.b = " <<&(ss.d.b) < cout << "ss.d = " <<&ss.e << endl; 98A ; R
print out 各个变量的内存地址不就可以看出来了吗。 {>Zc#U'
2mI=V.X[&
所以答案是24,2. #b:8-Lt:M
2@=JIMtc
但是我的想像中应该是这样的分布情况: /mvuSNk
c******* H!,#Z7s
aa**bbbb !\CoJ.5=
dddddddd C:W}hA!
>0{{loqq
不知为什么会c和a放在一起,组成8位长度。