Intel和微软同时出现的C语言面试题 jmW7)jT8:
#pragma pack(8) y1L,0 ]
7"D.L-H
struct s1{ )@bQu~Y
short a; C$)onk
long b; l%i+cO D
}; x'R`.
!g3
Od)C&N=y
struct s2{ 9(wK@
char c; \xoP)Ub>
s1 d; 0#^v{DC
long long e; <1M-Ro?5k
}; <p"iY}x[H
z*)T%p
#pragma pack() "g8M0[7e3
X!g#T9kG
问 Uf+%W;}
1.sizeof(s2) = ? y"wShAR
2.s2的s1中的a后面空了几个字节接着是b? -z(+/ /K:#
)w%!{hn
[j'X;tVX{
3sZ\0P}
如果您知道答案请在讨论中写出,以下是部份网友的答案,供参考: ,s;UfF
5l*&>C[(i
网友rwxybh(行云)的答案: G,w(d@
内存布局是 3=ymm^
1*** 11** u> 7=AlWF-
1111 **** 9'q*:&qq
1111 1111 N ZSSg2TX#
UFuX@Lu0
所以答案就是24和3 .kfIi^z
&@YmA1Yu)E
下面是一个测试的程序,试一试就知道了,我用的是VC2005 45>?o
{Y9q[D'g .
#pragma pack(8) !g2+w$YVa
sD wqH.L
struct s1{ lHX72s|V
short a; // 2 BYtes 2jhxQL
long b; // 4 Bytes 1|wL\I
}; f&
'
struct s2{ N] sAji*
char c; // 1 Byte ]z9=}=If
s1 d; // 8 Bytes HyWCMK6b
long long e; // 8 Bytes ?6Y?a2 |
}; D}/vLw :v
// 1*** 11** \)|hogI|f
// 1111 **** !C:$?oU
// 1111 1111 |$b}L7_
// ekCC5P!
#;nYg?d=
// 00 01 02 03 04 05 06 07 [cp+i^f
// 00 01 02 03 04 05 06 07 XpJ7o=?W3
// 00 01 02 03 04 05 06 07 n?Nt6U
// aw42oLk
#pragma pack() }`~+]9<
D,FkB"ZZE
int main(int argc, char* argv[]) b SU~XGPB
{ C3YT1tK
s2 a; 7Jho}5J
char *p = (char *)&a; ~Jz6O U*z
for(int i=0;i<24;++i) ixD)VcD-f
p = (char)(i%8); S^ \Vgi(
printf("%d\n",sizeof(a)); kW&TJP+5*
printf("c=0x%lx\n",a.c); Ek]'km!
printf("d.a=0x%x\n",a.d.a); BF{Y"8u$
printf("d.b=0x%x\n",a.d.b); emN*l]N
printf("e=0x%llx\n",a.e); S|`o]?nc>
return 0; dlTt_.
} ) hfpwdQ
结果: u4h4.NHX
24 <W $mj04@
c=0x0 Z?m3~L9L2
d.a=0x504 `+Q%oj#FF
d.b=0x3020100 j8lb~0JD
e=0x706050403020100 C>*u()q>4h
?<'}r7D
#4 pB@_
网友 redleaves (ID最吊的网友)的答案和分析: SI-Ops~e
jtc]>]6i
如果代码: NHZz _a=
#pragma pack(8) W9GVt$T7
struct S1{ %d<"l~<5;
char a; 7O-x<P;
long b; H~1jY4E
}; w&T9;_/
struct S2 {
Z>5b;8
char c; pg)WKbV
struct S1 d; *CI#+P
long long e; ut7zVp<"
}; [K0(RDV)%
#pragma pack() K(,F~.<
sizeof(S2)结果为24. [E juUElr
成员对齐有一个重要的条件,即每个成员分别对齐.即每个成员按自己的方式对齐. I4i>+:_J
也就是说上面虽然指定了按8字节对齐,但并不是所有的成员都是以8字节对齐.其对齐的规则是,每个成员按其类型的对齐参数(通常是这个类型的大小)和指定对齐参数(这里是8字节)中较小的一个对齐.并且结构的长度必须为所用过的所有对齐参数的整数倍,不够就补空字节. HCC#j9UN6
@r/nF5
S1中,成员a是1字节默认按1字节对齐,指定对齐参数为8,这两个值中取1,a按1字节对齐;成员b是4个字节,默认是按4字节对齐,这时就按4字节对齐,所以sizeof(S1)应该为8; oEZdd#*;
S2中,c和S1中的a一样,按1字节对齐,而d 是个结构,它是8个字节,它按什么对齐呢?对于结构来说,它的默认对齐方式就是它的所有成员使用的对齐参数中最大的一个,S1的就是4.所以,成员d就是按4字节对齐.成员e是8个字节,它是默认按8字节对齐,和指定的一样,所以它对到8字节的边界上,这时,已经使用了12个字节了,所以又添加了4个字节的空,从第16个字节开始放置成员e.这时,长度为24,已经可以被8(成员e按8字节对齐)整除.这样,一共使用了24个字节. %M|hA#04vZ
a b ckE-",G
S1的内存布局:11**,1111, _>X+ZlpU:
c S1.a S1.b d 8c^TT&
S2的内存布局:1***,11**,1111,****11111111 rCdu0 gYT
b2&0Hx
这里有三点很重要: vnZC,J `
1.每个成员分别按自己的方式对齐,并能最小化长度 U|Ta4W`k\
2.复杂类型(如结构)的默认对齐方式是它最长的成员的对齐方式,这样在成员是复杂类型时,可以最小化长度 ZX./P0
3.对齐后的长度必须是成员中最大的对齐参数的整数倍,这样在处理数组时可以保证每一项都边界对齐 `&c kZiq
.5ha}=z
.jWC$SVR
网友xue23(xue23) 的答案和分析: 1NA.nw.
^ sLdAC
有程序查一下各个变量的内存地址得知: N U`
各个变量在内存中的位置为 6gu!bu`~
c***aa** CdjI`
bbbb**** lchPpm9
dddddddd C1 GKLl~
测试代码为: cB}D^O
s2 ss; Vb]=B~ ^`
cout << "ss.c = " << &ss << endl ; x)O!["'"
cout << "ss.d.a = " <<&ss.d.a << endl; %2V? ,zY@
cout << "ss.d.b = " <<&(ss.d.b) < cout << "ss.d = " <<&ss.e << endl; K^<BW(s
print out 各个变量的内存地址不就可以看出来了吗。 &(l9?EVq1
#fn)k1
所以答案是24,2. ,M
^<CJ
pYmk1!]/
但是我的想像中应该是这样的分布情况: %S^8c
c******* .;`AAH'k
aa**bbbb K} X&AJ5A
dddddddd _TQj~W<
|[aiJR[Q
不知为什么会c和a放在一起,组成8位长度。