Intel和微软同时出现的C语言面试题 zzZK S
#pragma pack(8) 8&++S> <
6" |+\
struct s1{ Fes/8*-
short a; HsAKz]Mq
long b; k>!A~gfP~
}; A IsXu"
(zhi/>suG
struct s2{ u;=a=>05IR
char c; _A=Pr_kN
s1 d; [+>cW0a
long long e; uOQl;}Lk5
}; |gM@}!DL
]VHO'z\m
#pragma pack() .{66q#.
Ugv"A;l
问 Lb%:u5X\D@
1.sizeof(s2) = ? W3Dtt-)E
2.s2的s1中的a后面空了几个字节接着是b? /PgcW
^:,I #]
"[wP1n!G
T|ZJ$E0
如果您知道答案请在讨论中写出,以下是部份网友的答案,供参考: o7t#yw3
U$AV"F&!&}
网友rwxybh(行云)的答案: "78BApjWT6
内存布局是 '{:lP"\,L
1*** 11** xQ@gh
( (
1111 **** SD=9fh0l
1111 1111 DT>Giic
aDVBi: _
所以答案就是24和3 p^?]xD(
jt4c*0z
下面是一个测试的程序,试一试就知道了,我用的是VC2005 <hmRr
IjnO2X
#pragma pack(8) Qj(|uGqm3
F!~o J
struct s1{ QOKE9R#Y
short a; // 2 BYtes _.K<#S
long b; // 4 Bytes av4g/7=
}; ip2BvN&
struct s2{ |-.r9;-b
char c; // 1 Byte E:S (v
s1 d; // 8 Bytes kc}&\y
long long e; // 8 Bytes g;t>jgX
}; G|.5.FK^
// 1*** 11** 1g bqHxWI
// 1111 **** -+Ab[
// 1111 1111 s.KHm
L3
// ul[+vpH9
+oR wXO3W
// 00 01 02 03 04 05 06 07 0ZjinWkR[
// 00 01 02 03 04 05 06 07 SKrkB~%z
// 00 01 02 03 04 05 06 07 wEMg~Hh
// ,5/zTLd
#pragma pack() mybvD
j;_
>,\
int main(int argc, char* argv[]) A"R5Fd%6pc
{ Q:sw*7"F
s2 a; 6qkMB|@Ix
char *p = (char *)&a; $(ei<cAV
for(int i=0;i<24;++i) R,KoymXP
p = (char)(i%8); dMjAG7U
printf("%d\n",sizeof(a)); qo62!q
printf("c=0x%lx\n",a.c); M_EXA _
printf("d.a=0x%x\n",a.d.a); E6mwvrm8
printf("d.b=0x%x\n",a.d.b); J:JkX>n%k=
printf("e=0x%llx\n",a.e); R[_UbN 28
return 0; G$!JJ.
)d
} zd^QG
结果: ,pMH`
24 dsD!)$
c=0x0 )%=oJ!)
d.a=0x504 b$G&i'd
d.b=0x3020100 ELqpIXq#
e=0x706050403020100 3CArUP
@"gWvs
6;vfl*
网友 redleaves (ID最吊的网友)的答案和分析: 9_<>#)u5
FT+[[9i
如果代码: C
lekB
#pragma pack(8) Mo_(WSs
struct S1{ "0#d F:qt
char a; euc|G Xs
long b; *mTx0sQz(J
}; 1Wy0#?L
struct S2 { UA]U_P$c
char c; Jx_BjkF
struct S1 d; s6| S#
long long e; 2#?qey
}; |ZuS"'3_w
#pragma pack() CAvyS
sizeof(S2)结果为24. BA t0YE`-,
成员对齐有一个重要的条件,即每个成员分别对齐.即每个成员按自己的方式对齐. 1#-=|:U
也就是说上面虽然指定了按8字节对齐,但并不是所有的成员都是以8字节对齐.其对齐的规则是,每个成员按其类型的对齐参数(通常是这个类型的大小)和指定对齐参数(这里是8字节)中较小的一个对齐.并且结构的长度必须为所用过的所有对齐参数的整数倍,不够就补空字节. %`1p 8>n
tsvh/)V
S1中,成员a是1字节默认按1字节对齐,指定对齐参数为8,这两个值中取1,a按1字节对齐;成员b是4个字节,默认是按4字节对齐,这时就按4字节对齐,所以sizeof(S1)应该为8; Uel^rfE`
S2中,c和S1中的a一样,按1字节对齐,而d 是个结构,它是8个字节,它按什么对齐呢?对于结构来说,它的默认对齐方式就是它的所有成员使用的对齐参数中最大的一个,S1的就是4.所以,成员d就是按4字节对齐.成员e是8个字节,它是默认按8字节对齐,和指定的一样,所以它对到8字节的边界上,这时,已经使用了12个字节了,所以又添加了4个字节的空,从第16个字节开始放置成员e.这时,长度为24,已经可以被8(成员e按8字节对齐)整除.这样,一共使用了24个字节. T\Ld)'fNv
a b qKL
mL2O
S1的内存布局:11**,1111, N56/\1R
c S1.a S1.b d \c.MIDp"
S2的内存布局:1***,11**,1111,****11111111 "g>, X[g
)T26cT$
这里有三点很重要: y o
|"-
1.每个成员分别按自己的方式对齐,并能最小化长度 sAec*Q(R
2.复杂类型(如结构)的默认对齐方式是它最长的成员的对齐方式,这样在成员是复杂类型时,可以最小化长度 }Uc)iNU
3.对齐后的长度必须是成员中最大的对齐参数的整数倍,这样在处理数组时可以保证每一项都边界对齐 >p|tIST
eod-N}o
%
A8dO+W
网友xue23(xue23) 的答案和分析: /3ty*LQT
}4A $j{\
有程序查一下各个变量的内存地址得知: pwG" _|h
各个变量在内存中的位置为 vRn"0Mzl8
c***aa** ,U^V]jC
bbbb**** 2J5RZg9jL
dddddddd B8sc;Z.
测试代码为: `rLy7\@;
s2 ss; -AcVVK&
cout << "ss.c = " << &ss << endl ; cgevP`*]
cout << "ss.d.a = " <<&ss.d.a << endl; Y ~%9TC
cout << "ss.d.b = " <<&(ss.d.b) < cout << "ss.d = " <<&ss.e << endl; _Nmc1azS
print out 各个变量的内存地址不就可以看出来了吗。 Iurb?
[~#]p9|L
所以答案是24,2. ql_GN[c/
=@EX!]=x
但是我的想像中应该是这样的分布情况: (h3f$
c******* ?z$^4u3
aa**bbbb IGC:zZ~z
dddddddd O${B)C,
OELh6R
不知为什么会c和a放在一起,组成8位长度。