Intel和微软同时出现的C语言面试题 }!{R;,5/n
#pragma pack(8) by0K:*C
x`FTy&g
struct s1{ OF={k[
short a; pdR\Ne0P*
long b; G[JWG
}; N UvVhy]{
#rF`Hk:
struct s2{ _WvVF*Q"k
char c; J}[[tl
s1 d; maDWV&Db
long long e; mj ?Gc
}; gKl9Nkd!R
Sgv_YoD?-
#pragma pack() l*OR{!3H$
-b{<VrZ
问 cD6 ^7QF
1.sizeof(s2) = ? W7'<Jom|?
2.s2的s1中的a后面空了几个字节接着是b? [*5]NNB
8B &EH+
pDYJLh-C
[U",yN]d
如果您知道答案请在讨论中写出,以下是部份网友的答案,供参考: 343d`FRa}
W6}>iB
网友rwxybh(行云)的答案: q^<HG]
内存布局是 j'U1lEZm2
1*** 11** K:jn^JN$
1111 **** i!}6FBZ
1111 1111 Axns
2"?D aX
所以答案就是24和3 SepwMB4@
bEj}J_#
下面是一个测试的程序,试一试就知道了,我用的是VC2005 \?R#ZxP@
EnlAgL']|
#pragma pack(8) :H3/+/x
i0$*):b
struct s1{ Q.$Rhjb
short a; // 2 BYtes jc )7FE
long b; // 4 Bytes Ky"FL
}; ,dTmI{@O
struct s2{ V4NQcy?
H
char c; // 1 Byte 5 ,-8oEUL
s1 d; // 8 Bytes ohqThl
long long e; // 8 Bytes $l"%o9ICG
}; =?0v,;F9|
// 1*** 11** !L9OJ1F
// 1111 **** s5{=lP
// 1111 1111 {pH# zs4Y
// cQuL9Xo
_"B.V(
// 00 01 02 03 04 05 06 07 xl`AiO `K
// 00 01 02 03 04 05 06 07 zs Q|LwQ
// 00 01 02 03 04 05 06 07 K$Vu[!l`
// ("t'XKP&N
#pragma pack() ,>rvl P
{R-o8N
int main(int argc, char* argv[]) O+|C<;K
{ n<j+KD#a
s2 a; Pb>/b\&JS
char *p = (char *)&a; YLQ0UeDN'
for(int i=0;i<24;++i) ws5Ue4g|
p = (char)(i%8); KS93v9|
printf("%d\n",sizeof(a)); 3sdL\
printf("c=0x%lx\n",a.c); qE[YZ(/f0&
printf("d.a=0x%x\n",a.d.a); vs=q<Uw)
printf("d.b=0x%x\n",a.d.b); "lw|EpQk`
printf("e=0x%llx\n",a.e); |&JeJ0k>~
return 0; }}$@Tij19[
} Znb7OF^#"
结果: O#ZZ PJ"
24 QHZ",1F
c=0x0 o zn&>k
d.a=0x504 -grf7w^
d.b=0x3020100 Y2QX<
e=0x706050403020100 zaHZ5%{LQD
b{
x lW }S
s+lBai*#
网友 redleaves (ID最吊的网友)的答案和分析: B8T$<
|mQ Fi\
如果代码: $U]T8;5Q
#pragma pack(8) #DFi-o&-
struct S1{ &H;,,7u
char a; _C?Wk:Y@
long b; i cTpx#|=
}; MXcW
&b
struct S2 { x+Xd7N1
char c; aqI"4v]~b
struct S1 d; D?1fY!C:r
long long e; $xZ ~bE9
}; Cn3_D
#pragma pack()
SW#/;|m
sizeof(S2)结果为24. f;
|fS~
成员对齐有一个重要的条件,即每个成员分别对齐.即每个成员按自己的方式对齐. zZCRej
也就是说上面虽然指定了按8字节对齐,但并不是所有的成员都是以8字节对齐.其对齐的规则是,每个成员按其类型的对齐参数(通常是这个类型的大小)和指定对齐参数(这里是8字节)中较小的一个对齐.并且结构的长度必须为所用过的所有对齐参数的整数倍,不够就补空字节. xt5/`C
`T[@ -
S1中,成员a是1字节默认按1字节对齐,指定对齐参数为8,这两个值中取1,a按1字节对齐;成员b是4个字节,默认是按4字节对齐,这时就按4字节对齐,所以sizeof(S1)应该为8; R\3a Sx L
S2中,c和S1中的a一样,按1字节对齐,而d 是个结构,它是8个字节,它按什么对齐呢?对于结构来说,它的默认对齐方式就是它的所有成员使用的对齐参数中最大的一个,S1的就是4.所以,成员d就是按4字节对齐.成员e是8个字节,它是默认按8字节对齐,和指定的一样,所以它对到8字节的边界上,这时,已经使用了12个字节了,所以又添加了4个字节的空,从第16个字节开始放置成员e.这时,长度为24,已经可以被8(成员e按8字节对齐)整除.这样,一共使用了24个字节. D;V[9E=g/
a b NUltuM
S1的内存布局:11**,1111, e9KD mX_
c S1.a S1.b d YP_L~zZ
S2的内存布局:1***,11**,1111,****11111111 I61S0lz/
g) u%?T
这里有三点很重要: Vz/w.%_g
1.每个成员分别按自己的方式对齐,并能最小化长度 _=s9o/Cn]
2.复杂类型(如结构)的默认对齐方式是它最长的成员的对齐方式,这样在成员是复杂类型时,可以最小化长度 -Y/i
h(I^
3.对齐后的长度必须是成员中最大的对齐参数的整数倍,这样在处理数组时可以保证每一项都边界对齐 O+=%Mz(l
4kM/`g6?,q
!B%em%Tv
网友xue23(xue23) 的答案和分析: xrg?{*\
Y)X7*iTi'j
有程序查一下各个变量的内存地址得知: E@ U]k$M
各个变量在内存中的位置为 bJ!\eI%ld
c***aa** JyMk @Y
bbbb**** M/Yr0"%Q<.
dddddddd +`Z1L\gmA
测试代码为: NAvR^"I~
s2 ss; !|&|%x6@
cout << "ss.c = " << &ss << endl ; *tF~CG$r
cout << "ss.d.a = " <<&ss.d.a << endl; wL?Up>fr
cout << "ss.d.b = " <<&(ss.d.b) < cout << "ss.d = " <<&ss.e << endl; v&YeQC>
print out 各个变量的内存地址不就可以看出来了吗。 ( *+'k1Ea
2P"9m
所以答案是24,2. <(lA
CH
=WY'n
l'
但是我的想像中应该是这样的分布情况: 1z-.e$&z
c******* Kk8}m;
aa**bbbb ~U&NY7.@
dddddddd AYA{_^#+3
,D+ydr
不知为什么会c和a放在一起,组成8位长度。