Intel和微软同时出现的C语言面试题 NmSo4Dg`U
#pragma pack(8) Vo"RO$%ow*
Rv/Bh<t
struct s1{ kWrp1`
short a; e~"fn*"
long b; $]q8,
N|1
}; H/"lAXfb
v%RP0%%{s
struct s2{ A2nqf^b{#
char c; kn/Ao}J74z
s1 d; YXI'gn2b#
long long e; l3IWoa&sh
}; Y!T
%cTK)a
}YHX-e<Yx]
#pragma pack() lbuAE%
EMc;^ d
问 DK
oN}c
1.sizeof(s2) = ? E.U_W
2.s2的s1中的a后面空了几个字节接着是b? O/!bG~\Y
]7rj/l$u
8zBWIi
RTFZPq84
如果您知道答案请在讨论中写出,以下是部份网友的答案,供参考: V14B[|YM<
.YZgOJi
网友rwxybh(行云)的答案: >|Cw\^
内存布局是 R+7oRXsu
1*** 11** %.z,+Zz?
1111 **** A?@@*$&
1111 1111 &EpAg@9!
CQpCS_M
所以答案就是24和3 DSj(]U~r
UYz0PSV=.
下面是一个测试的程序,试一试就知道了,我用的是VC2005 i>joT><B
z-c}NdW
#pragma pack(8) N72Yq)(
MG?0>^F
struct s1{ }E7:ihy
short a; // 2 BYtes ai0Ut
long b; // 4 Bytes +nT'I!//
}; R9!Uo
struct s2{ G!XIc>F*
char c; // 1 Byte 2m~V{mUT!
s1 d; // 8 Bytes yu;SH[{Wi
long long e; // 8 Bytes e*.b3z
}; W.w)H@]7m
// 1*** 11** r
lKlpl
// 1111 **** U`]T~9I
// 1111 1111 84{Q\c
// A%2:E^k(s
mB0l "# F
// 00 01 02 03 04 05 06 07 1U,1)<z~u
// 00 01 02 03 04 05 06 07 QL$S4 J"
// 00 01 02 03 04 05 06 07 /QEiMrz@6
// 1*
]Ev
#pragma pack() /o2P+Xr8"
.uE Pnzi
int main(int argc, char* argv[]) 8j4z{+'TQ
{ bTSL<"(]N
s2 a; =GXu 5 8
char *p = (char *)&a; *;XWLd#
for(int i=0;i<24;++i) Y+3!f#exm
p = (char)(i%8); $:of=WTY(
printf("%d\n",sizeof(a)); u@3y&b
printf("c=0x%lx\n",a.c); A?*o0I
printf("d.a=0x%x\n",a.d.a); o5n^!gi4
printf("d.b=0x%x\n",a.d.b); v-! u\
printf("e=0x%llx\n",a.e); c c
return 0; HQ9X7[3
} W<<9y
结果: ~RD+.A
24 ]1gx#y 2
c=0x0 YKa0H%B(
d.a=0x504 ~j'l.gQb
d.b=0x3020100 "p3_y`h6+
e=0x706050403020100 8_!.!Kde |
v{<[)cr
P5gN #G
网友 redleaves (ID最吊的网友)的答案和分析: oW;6h.
]LZ`LL'#Y_
如果代码: 99EXo+g
#pragma pack(8) [0UGuj
struct S1{ eVl'\aUd
char a; J4YBqp
long b; :ZDMNhUl
&
}; RJeSi`19T)
struct S2 { T,_(?YJW
char c; /(8a~f&%r
struct S1 d; TH &qX
long long e; ++Ww88820
}; 5#E |R
#pragma pack() wJlX4cT4YV
sizeof(S2)结果为24. b5:op@V
成员对齐有一个重要的条件,即每个成员分别对齐.即每个成员按自己的方式对齐. wl1m*`$
也就是说上面虽然指定了按8字节对齐,但并不是所有的成员都是以8字节对齐.其对齐的规则是,每个成员按其类型的对齐参数(通常是这个类型的大小)和指定对齐参数(这里是8字节)中较小的一个对齐.并且结构的长度必须为所用过的所有对齐参数的整数倍,不够就补空字节. Yh)Isg|0>
NS C/@._
S1中,成员a是1字节默认按1字节对齐,指定对齐参数为8,这两个值中取1,a按1字节对齐;成员b是4个字节,默认是按4字节对齐,这时就按4字节对齐,所以sizeof(S1)应该为8; "<i SZ
S2中,c和S1中的a一样,按1字节对齐,而d 是个结构,它是8个字节,它按什么对齐呢?对于结构来说,它的默认对齐方式就是它的所有成员使用的对齐参数中最大的一个,S1的就是4.所以,成员d就是按4字节对齐.成员e是8个字节,它是默认按8字节对齐,和指定的一样,所以它对到8字节的边界上,这时,已经使用了12个字节了,所以又添加了4个字节的空,从第16个字节开始放置成员e.这时,长度为24,已经可以被8(成员e按8字节对齐)整除.这样,一共使用了24个字节. CD0VfA>Z
a b )RsM!}
S1的内存布局:11**,1111, dXn%lJ
c S1.a S1.b d 5TUNX^AW
S2的内存布局:1***,11**,1111,****11111111 s9oO%e<
LG]3hz9^9
这里有三点很重要: #Z~C`n
u
1.每个成员分别按自己的方式对齐,并能最小化长度 %5\3Aw
2.复杂类型(如结构)的默认对齐方式是它最长的成员的对齐方式,这样在成员是复杂类型时,可以最小化长度 [= "r<W0
3.对齐后的长度必须是成员中最大的对齐参数的整数倍,这样在处理数组时可以保证每一项都边界对齐 %/.a]j!
=?X$Yaw*
` rm?a0
网友xue23(xue23) 的答案和分析: B[9 (FRX
PNeh#PI6)
有程序查一下各个变量的内存地址得知: <:|3rfm#
各个变量在内存中的位置为 tU/k-W3X
c***aa** q:8_]Qt
bbbb**** voe7l+Xk
dddddddd 3CE[(
测试代码为: @uH#qg7
s2 ss; FP"$tt (
cout << "ss.c = " << &ss << endl ; V,ZY*f0
cout << "ss.d.a = " <<&ss.d.a << endl; kVS?RHR
cout << "ss.d.b = " <<&(ss.d.b) < cout << "ss.d = " <<&ss.e << endl; n+1y
print out 各个变量的内存地址不就可以看出来了吗。 Rb}KZ+o"Z
i.1U|Pi
所以答案是24,2. 2yo
cu!4l
/Y^8SO4
但是我的想像中应该是这样的分布情况: o0z67(N&g
c******* DW(~Qdk
aa**bbbb nkeI60
dddddddd k6\^p;!Y
!~-6wN"k
不知为什么会c和a放在一起,组成8位长度。