Intel和微软同时出现的C语言面试题 FQcm=d_s
#pragma pack(8) 0- u,AD
(AHTv8
struct s1{ #c-Jo[%G
short a; q\Z9.T+Qo
long b; %@%~<U)W
}; YW"nPZNPy~
nDNK}O~'
struct s2{ 'f6!a5qC
char c; O\w-hk
s1 d; 4n%|h-!8
long long e; KCn#*[
}; ,_:6qn{
+@<@x4yt
#pragma pack() zZV9`cqZ{
]K<7A!+@@p
问 H)K.2Q
1.sizeof(s2) = ? oB+@05m8
2.s2的s1中的a后面空了几个字节接着是b? ]Yf8
mQ\oR|
TaZlfe5z
r6kQMFA
如果您知道答案请在讨论中写出,以下是部份网友的答案,供参考: N
Q}5'
+sXnC\
网友rwxybh(行云)的答案: s_6Iz^]I
内存布局是 H#QPcp@
1*** 11** GGFrV8
1111 **** FOqD
1111 1111 Qe=eer~jI
lsVg'k/Z!
所以答案就是24和3 q{7+N1
"
5_SxX@fW%
下面是一个测试的程序,试一试就知道了,我用的是VC2005 u)l[*";S
&>XSQB(&%
#pragma pack(8) kqLpt
[O6JVXO>
struct s1{ "mcuF]7F
short a; // 2 BYtes _61tE
long b; // 4 Bytes [V;Q#r&+
};
0|?DA12Z
struct s2{ QW&@>i
char c; // 1 Byte {;hRFQ^b
s1 d; // 8 Bytes K?V'
?s
long long e; // 8 Bytes M'$?Jp#]}
}; wVUm!Y
// 1*** 11** XMpE|M!c
// 1111 **** smX&B,&@
// 1111 1111 7] 17?s]t,
// WQHlf0]
vFK(Dx
// 00 01 02 03 04 05 06 07 1(4IcIR5T;
// 00 01 02 03 04 05 06 07 N'8}5Kx5
// 00 01 02 03 04 05 06 07 ))uki*UNK
// 1@`mpm#Y
#pragma pack() $PTl{
=`wnng5m
int main(int argc, char* argv[]) \Qz
{ 7[(<t+
s2 a; C6:;
T%
char *p = (char *)&a; %X(|Z4dL
for(int i=0;i<24;++i) >orDw3xC
p = (char)(i%8); {^Q1b.=
printf("%d\n",sizeof(a)); >8DZj&j
printf("c=0x%lx\n",a.c); \eS-wO7%
printf("d.a=0x%x\n",a.d.a); !:|D[1m
printf("d.b=0x%x\n",a.d.b); S&~;l/
printf("e=0x%llx\n",a.e); @|9V]bk
return 0; 7XiR)jYo*
} m# I
结果: G88g@Exk
24 -}Gk@=$G
c=0x0 ;5=5HYx%
d.a=0x504 ~)!vhdBe
d.b=0x3020100 [1.>9ngj
e=0x706050403020100 ](^BQc
50`<[w<J
q
FdmoR;
网友 redleaves (ID最吊的网友)的答案和分析: )>WSuf
j
%<'PSri
如果代码: \@*D;-b
#pragma pack(8) fngk<$lvg
struct S1{ !*=+E%7
char a; [f-<M@id/
long b; >^d+;~Q;
}; fvw&y+|y!
struct S2 { c+]5[6
char c; +q)B4A'J!
struct S1 d; 'M3V#5l)@|
long long e; SWMi+)
}; o%?~9rf]]
#pragma pack() M\bea
sizeof(S2)结果为24. 8f-B-e?k
成员对齐有一个重要的条件,即每个成员分别对齐.即每个成员按自己的方式对齐. RQd5Q.
也就是说上面虽然指定了按8字节对齐,但并不是所有的成员都是以8字节对齐.其对齐的规则是,每个成员按其类型的对齐参数(通常是这个类型的大小)和指定对齐参数(这里是8字节)中较小的一个对齐.并且结构的长度必须为所用过的所有对齐参数的整数倍,不够就补空字节. ~@EBW3>~5
@m ?&7{y#?
S1中,成员a是1字节默认按1字节对齐,指定对齐参数为8,这两个值中取1,a按1字节对齐;成员b是4个字节,默认是按4字节对齐,这时就按4字节对齐,所以sizeof(S1)应该为8; O:te;lQK
S2中,c和S1中的a一样,按1字节对齐,而d 是个结构,它是8个字节,它按什么对齐呢?对于结构来说,它的默认对齐方式就是它的所有成员使用的对齐参数中最大的一个,S1的就是4.所以,成员d就是按4字节对齐.成员e是8个字节,它是默认按8字节对齐,和指定的一样,所以它对到8字节的边界上,这时,已经使用了12个字节了,所以又添加了4个字节的空,从第16个字节开始放置成员e.这时,长度为24,已经可以被8(成员e按8字节对齐)整除.这样,一共使用了24个字节. #Pq.^ ^
a b Z$Mc{
S1的内存布局:11**,1111, 8J+:5b_?
c S1.a S1.b d 9rQw~B<S
S2的内存布局:1***,11**,1111,****11111111 w_^g-P[o-
HiDL:14
这里有三点很重要: e{`DvfY21
1.每个成员分别按自己的方式对齐,并能最小化长度 v/}hy$7
2.复杂类型(如结构)的默认对齐方式是它最长的成员的对齐方式,这样在成员是复杂类型时,可以最小化长度 C-L["O0[
3.对齐后的长度必须是成员中最大的对齐参数的整数倍,这样在处理数组时可以保证每一项都边界对齐 M9dUo7
|%7OI#t^
N^By#Z
网友xue23(xue23) 的答案和分析: "%{J$o
#wZBWTj.
有程序查一下各个变量的内存地址得知: J l9w/T
各个变量在内存中的位置为 Ke,$3Yx
c***aa** Lw #vHNf6
bbbb**** aT%6d@g
dddddddd bY7~b/
测试代码为: naWW i]9
s2 ss; rJ_fg$.<
cout << "ss.c = " << &ss << endl ; '5m`[S-IU
cout << "ss.d.a = " <<&ss.d.a << endl; zu|=1C#5h
cout << "ss.d.b = " <<&(ss.d.b) < cout << "ss.d = " <<&ss.e << endl; /,#&Htk
print out 各个变量的内存地址不就可以看出来了吗。 :TN^}RML
p+d?k"WN?
所以答案是24,2. k6W
[//
pbb6?R,
但是我的想像中应该是这样的分布情况: F5;x>;r
c******* \l9S5%L9
aa**bbbb 4|DGQ
dddddddd Dh{sVRA
b0"R |d[i
不知为什么会c和a放在一起,组成8位长度。