Intel和微软同时出现的C语言面试题 , a2=OV
#pragma pack(8) ^H&`e"|R9
#?>pl.
struct s1{
Cz&t*i/
short a; *
+6Z^7
long b; x>J(3I5_b
}; 5lwMc0{/3
7~N4~KAUS
struct s2{ "r@G V5ED
char c; $RC)e7
s1 d; elD|b=(-
long long e; c4Q%MRR
}; X
VH(zJ
FId,/la
#pragma pack() NJ$Qm.S
f&Sovuuh
问 #z*,-EV|
1.sizeof(s2) = ? 3^)c5kcI
2.s2的s1中的a后面空了几个字节接着是b? UQb|J9HY4
:8v? 6Q
I34
1s0
9m"EY@-
如果您知道答案请在讨论中写出,以下是部份网友的答案,供参考: XZTH[#MqeI
e!k4Ij-]
网友rwxybh(行云)的答案: eG dFupfz
内存布局是 G]Im.x3O-
1*** 11** z_(4
1111 **** au+:-Khm
1111 1111 W:}t%agis
fQw=z$
所以答案就是24和3 G}dq
ft5"
5RF*c,cNq
下面是一个测试的程序,试一试就知道了,我用的是VC2005 GJF
,w{J
%Go/\g
#pragma pack(8) XHJ/211
9`&sZ|"3
struct s1{ |uM=pm;H
short a; // 2 BYtes ZlQ&m
long b; // 4 Bytes d]?fL&jr
}; & TN.6Hm3
struct s2{ --vJR/-
char c; // 1 Byte i\K88B&24
s1 d; // 8 Bytes {s2eOL5I|%
long long e; // 8 Bytes \5HVX/
}; !|J2o8g
// 1*** 11** =6qSo
@
// 1111 **** MTbCL53!-
// 1111 1111 >Gvd?r
// kWCxc0
#zb6 7mg~
// 00 01 02 03 04 05 06 07 M2qor.d
// 00 01 02 03 04 05 06 07 P;IM -]
// 00 01 02 03 04 05 06 07 W$gjcsv
// (|tR>R.Wxg
#pragma pack() sv!6zJs
_( QW2m?K
int main(int argc, char* argv[]) *M$$%G(4
{ E7<l^/<2S+
s2 a; J8&0l&~6
char *p = (char *)&a; &~=d;llkT
for(int i=0;i<24;++i) LO%OH
u}]
p = (char)(i%8); }fhGofN$e
printf("%d\n",sizeof(a)); BMn`t@ !x
printf("c=0x%lx\n",a.c); , LqfwA|
printf("d.a=0x%x\n",a.d.a); y
XCZs
printf("d.b=0x%x\n",a.d.b); L*{E-m/
printf("e=0x%llx\n",a.e); SU. $bsu
return 0; s}4k^NGFJ
} $o
;48uV^
结果: 0.U-
tg0
24 (J
j'kW6G6
c=0x0 E8aD[j[w
d.a=0x504 ~x+&cA-0A2
d.b=0x3020100 &i*e&{L7
e=0x706050403020100 B\~(:(OPM]
QC1\Sn /
0"mr*hyj
网友 redleaves (ID最吊的网友)的答案和分析: ]];LA!n
IKp/xj[!
如果代码: T4;gF6(0]
#pragma pack(8) 78IY&q:v&0
struct S1{ U6YQ*%mZ_
char a; \.=,}sV2Z
long b; L~Xzo
}; "~08<+
struct S2 { c$;Cpt@-j
char c; byk9"QeY\
struct S1 d; Se!B,'C%
long long e; 0.^67'
}; PJ)d5D%T
#pragma pack() %^iBTfq2hc
sizeof(S2)结果为24. MX|@x~9W
成员对齐有一个重要的条件,即每个成员分别对齐.即每个成员按自己的方式对齐. _u#r;h[
也就是说上面虽然指定了按8字节对齐,但并不是所有的成员都是以8字节对齐.其对齐的规则是,每个成员按其类型的对齐参数(通常是这个类型的大小)和指定对齐参数(这里是8字节)中较小的一个对齐.并且结构的长度必须为所用过的所有对齐参数的整数倍,不够就补空字节. 5^N`~
WG&WPV/p
S1中,成员a是1字节默认按1字节对齐,指定对齐参数为8,这两个值中取1,a按1字节对齐;成员b是4个字节,默认是按4字节对齐,这时就按4字节对齐,所以sizeof(S1)应该为8; VE^IA\J x
S2中,c和S1中的a一样,按1字节对齐,而d 是个结构,它是8个字节,它按什么对齐呢?对于结构来说,它的默认对齐方式就是它的所有成员使用的对齐参数中最大的一个,S1的就是4.所以,成员d就是按4字节对齐.成员e是8个字节,它是默认按8字节对齐,和指定的一样,所以它对到8字节的边界上,这时,已经使用了12个字节了,所以又添加了4个字节的空,从第16个字节开始放置成员e.这时,长度为24,已经可以被8(成员e按8字节对齐)整除.这样,一共使用了24个字节. X/D%
cQ6
a b NLev(B:OQH
S1的内存布局:11**,1111, [-nPHmZV[
c S1.a S1.b d G;J!3A;TE
S2的内存布局:1***,11**,1111,****11111111 TTSq }sb}
Ge*N%=MX8
这里有三点很重要: [qxDCuxq
1.每个成员分别按自己的方式对齐,并能最小化长度 y# IUDnRJ
2.复杂类型(如结构)的默认对齐方式是它最长的成员的对齐方式,这样在成员是复杂类型时,可以最小化长度 CmtDfE
3.对齐后的长度必须是成员中最大的对齐参数的整数倍,这样在处理数组时可以保证每一项都边界对齐 [tJp^?6*
z2;<i|Ez0
xv_Z$&9e>l
网友xue23(xue23) 的答案和分析: ]ia{N
8@KGc
)k
有程序查一下各个变量的内存地址得知:
\Bl`;uXb
各个变量在内存中的位置为 YcM0A~<
c***aa** m3`J9f,c/
bbbb**** y6>fK@K~
dddddddd ~@D{&7@
测试代码为: i MF-TR
s2 ss; z+j3j2
cout << "ss.c = " << &ss << endl ; 7C~g?1
cout << "ss.d.a = " <<&ss.d.a << endl; $T*g@]
cout << "ss.d.b = " <<&(ss.d.b) < cout << "ss.d = " <<&ss.e << endl; 8HDI]
print out 各个变量的内存地址不就可以看出来了吗。 ^B(:Hv}G(:
YF)c.Q0
所以答案是24,2. oox;8d4}y
ezhK[/E=
但是我的想像中应该是这样的分布情况: LP}'upv
c******* ({hW
aa**bbbb Ka8Bed3
dddddddd KY9@2JG
&hIr@Gi@ch
不知为什么会c和a放在一起,组成8位长度。