Intel和微软同时出现的C语言面试题 *1v[kWa?
#pragma pack(8) hEBY8=gK
}% `.h"
struct s1{
f4Xk,1Is
short a; @)|C/oA
long b; 5Ow[~p"l<
}; F<qz[,]|-j
*h'=3w:G
struct s2{ -o!$tI&
char c; 3QG7C{
s1 d; "JlpU-8[0@
long long e; :-/M?,Q"
}; 8,C*4y~
bYEy<7)x
#pragma pack() }T&iewk
ldiD2
Q
问 Fs9I7~L3
1.sizeof(s2) = ? "uaMk}[ <!
2.s2的s1中的a后面空了几个字节接着是b? lfqiyYFm
t
m7^yn:
f"%{%M$K
+y&Tf#.V/A
如果您知道答案请在讨论中写出,以下是部份网友的答案,供参考: y%%}k
bgK'{_o-
网友rwxybh(行云)的答案: 7R6ry(6N
内存布局是 l)Crc-:}4j
1*** 11** ^; )8VP6
1111 **** @\f^0^G
1111 1111 S/9DtXQ
,n3a
gkPO>
所以答案就是24和3 9%B\/&f
Dey<OE&
下面是一个测试的程序,试一试就知道了,我用的是VC2005 @GdbTd
";3zXk[#
#pragma pack(8) vUohtS*
3NqN\5B:
struct s1{ _*1`@
short a; // 2 BYtes L)@?e?9
long b; // 4 Bytes M<kj_.
}; B56L1^7
struct s2{ !,6c ~ w
char c; // 1 Byte ~N<4L>y<
s1 d; // 8 Bytes z([ v%zf
long long e; // 8 Bytes 7f0lQ
}; K`u(/kz/<
// 1*** 11** `HZ;NRr
// 1111 **** \$*7 >`k
// 1111 1111 8B\2Zfe
// PIdikA
xI($Uu}S
// 00 01 02 03 04 05 06 07 #a'Ex=%rM
// 00 01 02 03 04 05 06 07 G!>z;5KuS
// 00 01 02 03 04 05 06 07 ??M"6k
// tt0f-:#
#pragma pack() |mGFts}0o'
O(D~_O.
int main(int argc, char* argv[]) Wu[&Wv~
{ q*_/to
s2 a; <{V(.=11
char *p = (char *)&a; 60J;sGW
for(int i=0;i<24;++i) '>cKH$nVC}
p = (char)(i%8); [5G6VNh=
printf("%d\n",sizeof(a)); y9q8i(E0
printf("c=0x%lx\n",a.c); K/i*w<aPb7
printf("d.a=0x%x\n",a.d.a); NG "C&v
printf("d.b=0x%x\n",a.d.b); 6kpg+{;
printf("e=0x%llx\n",a.e); gy#/D& N[
return 0; f&BY/ n,
} #_6I w`0
结果: 3Z5D)zuc
24 /fZeWU0W
c=0x0 VH9dleZ
d.a=0x504 /{+y2.{j
d.b=0x3020100 mRL"nC
e=0x706050403020100 "D63I|O)
+jS|2d
Sdt`i
网友 redleaves (ID最吊的网友)的答案和分析: 6$kq aS##
qU%/W|LY
如果代码: r^FhTzA=1
#pragma pack(8) [fAV5U
struct S1{ GFeQ%l`7F
char a; Qw-~>d
long b; QEz?w}b*
}; dIN$)?aB0
struct S2 { {1UQ/_
char c; F5P[dp-`1
struct S1 d; -w9pwB
long long e; JMrEFk
}; SxOC1+Oy
#pragma pack() TW)c#P43K
sizeof(S2)结果为24. (s.0PO`
成员对齐有一个重要的条件,即每个成员分别对齐.即每个成员按自己的方式对齐. c6h.iBJ'
也就是说上面虽然指定了按8字节对齐,但并不是所有的成员都是以8字节对齐.其对齐的规则是,每个成员按其类型的对齐参数(通常是这个类型的大小)和指定对齐参数(这里是8字节)中较小的一个对齐.并且结构的长度必须为所用过的所有对齐参数的整数倍,不够就补空字节. QRHu3w
{:6r;TB
S1中,成员a是1字节默认按1字节对齐,指定对齐参数为8,这两个值中取1,a按1字节对齐;成员b是4个字节,默认是按4字节对齐,这时就按4字节对齐,所以sizeof(S1)应该为8; ,}3
'I [
S2中,c和S1中的a一样,按1字节对齐,而d 是个结构,它是8个字节,它按什么对齐呢?对于结构来说,它的默认对齐方式就是它的所有成员使用的对齐参数中最大的一个,S1的就是4.所以,成员d就是按4字节对齐.成员e是8个字节,它是默认按8字节对齐,和指定的一样,所以它对到8字节的边界上,这时,已经使用了12个字节了,所以又添加了4个字节的空,从第16个字节开始放置成员e.这时,长度为24,已经可以被8(成员e按8字节对齐)整除.这样,一共使用了24个字节. w,#>G07D
a b em,u(#)&
S1的内存布局:11**,1111, "i y
c S1.a S1.b d fmU {
S2的内存布局:1***,11**,1111,****11111111 w65K[l;2
K2TcOFQ
这里有三点很重要: CyS$|E
1.每个成员分别按自己的方式对齐,并能最小化长度 &]`(v}`]
2.复杂类型(如结构)的默认对齐方式是它最长的成员的对齐方式,这样在成员是复杂类型时,可以最小化长度 ''yB5#^w(
3.对齐后的长度必须是成员中最大的对齐参数的整数倍,这样在处理数组时可以保证每一项都边界对齐 0?s|i :
r[|Xy>Zj
',9V|jvK
网友xue23(xue23) 的答案和分析: 't:;irLW.
OI|[roMK
有程序查一下各个变量的内存地址得知: b$N2z
各个变量在内存中的位置为 9IjIIM2y
c***aa** yA)/Q
Yge
bbbb**** \pPY37l
dddddddd X <f8,n
测试代码为: [xSF6
s2 ss; B
Wk/DVue
cout << "ss.c = " << &ss << endl ; zr-*$1eu
cout << "ss.d.a = " <<&ss.d.a << endl; tXNm$Cq.|
cout << "ss.d.b = " <<&(ss.d.b) < cout << "ss.d = " <<&ss.e << endl; !%CWZZ 6u
print out 各个变量的内存地址不就可以看出来了吗。 e7^mmm
~xkeuU
所以答案是24,2. J\+0[~~
B^4&-z2|
但是我的想像中应该是这样的分布情况: E{XH?_xo
c******* kZR8a(4D
aa**bbbb HVi'eNgo
dddddddd pmuvg6@h
@:+8?qcP
不知为什么会c和a放在一起,组成8位长度。