Intel和微软同时出现的C语言面试题 RLypWjMx$
#pragma pack(8)
uC3o@qGW<
\dyJ=tg
struct s1{ _Ee`Uk
short a; C043h?x
long b; z$3 3NM
}; {iP^51fy
|~mi6 lJ6
struct s2{ M DnT
char c; ZQT14. $L
s1 d; m6aq_u{W
long long e; Ni5~Buf
}; la ~T)U7
U!:Q|':=h
#pragma pack() D6iHkDTg
ti:qOSIDTA
问 7$(>Z^ Em
1.sizeof(s2) = ? a!,q\p8<t0
2.s2的s1中的a后面空了几个字节接着是b? ~q]+\qty4
z6)SaSYE
10v4k<xb
6V= 69}
如果您知道答案请在讨论中写出,以下是部份网友的答案,供参考: Q 'R@'W9
})OgsBk
网友rwxybh(行云)的答案: `}1IQ.3
内存布局是 B2~KkMF
1*** 11** r5qp[Ss3F
1111 **** NymS8hxR
1111 1111 =J0X{Ovn4z
x+zz:^yHYf
所以答案就是24和3 esH>NH_
'CT8vt;
下面是一个测试的程序,试一试就知道了,我用的是VC2005 ^l#Z*0@><~
#vi `2F
#pragma pack(8) RVv@x5
TIg3'au
struct s1{ od{b]HvgS
short a; // 2 BYtes y]5O45E0
long b; // 4 Bytes ;BV1E|j
}; 4P@Ak7iL(V
struct s2{ a3i4eGT -
char c; // 1 Byte 2R&msdF
s1 d; // 8 Bytes }
h|1H
long long e; // 8 Bytes \*x]xc/^
}; eK\1cs
// 1*** 11** [HB>\
// 1111 **** YEoQIR
// 1111 1111 xzg81sV7
// 'c 0]8Y4
1 dT1DcZ
// 00 01 02 03 04 05 06 07 n?*Fr sZ
// 00 01 02 03 04 05 06 07 "nXL7N0
// 00 01 02 03 04 05 06 07 l~,5)*T
// d\}r.pD
#pragma pack() 0
;$[
<6`_Xr7)
int main(int argc, char* argv[]) ?yfk d:WD
{ gF;i3OJg
s2 a; n7`R+4/s
char *p = (char *)&a; !es?GJq`
for(int i=0;i<24;++i) M]YK]VyG
p = (char)(i%8); Z@fMU2e=Z
printf("%d\n",sizeof(a)); 2xvTijO0
printf("c=0x%lx\n",a.c); )CQ'kHT<e
printf("d.a=0x%x\n",a.d.a); z=>U>
printf("d.b=0x%x\n",a.d.b); <A +VS
printf("e=0x%llx\n",a.e); R]e?<,"X
return 0; c%_I|h<?iT
} !6:kJL}U
结果: RiC1lCE
24 LutP&Ebt8
c=0x0 "ewSh<t
d.a=0x504 Fyy)665x/
d.b=0x3020100 A+*M<W
e=0x706050403020100 d@~Hp?
d^sS{m\
~a KxwH
网友 redleaves (ID最吊的网友)的答案和分析: bD[W`yW0
)IQa]A
如果代码: A{mv[x-XN
#pragma pack(8) BtS#I[-p_
struct S1{ 5q<AMg
char a; Lu!o!>b
long b; X(Gp3lG
}; :,03)[u{8
struct S2 { &U%AVD[
char c; ?s[ kUv+=
struct S1 d; uc]]zI6
long long e; -ju&"L B
}; 1e.V%!Xk
#pragma pack() ,h,DB=!K<
sizeof(S2)结果为24. /1ZRjf^
成员对齐有一个重要的条件,即每个成员分别对齐.即每个成员按自己的方式对齐. cl
kL)7RQ
也就是说上面虽然指定了按8字节对齐,但并不是所有的成员都是以8字节对齐.其对齐的规则是,每个成员按其类型的对齐参数(通常是这个类型的大小)和指定对齐参数(这里是8字节)中较小的一个对齐.并且结构的长度必须为所用过的所有对齐参数的整数倍,不够就补空字节. Lu,72i0O ^
Tg|0!0qD]F
S1中,成员a是1字节默认按1字节对齐,指定对齐参数为8,这两个值中取1,a按1字节对齐;成员b是4个字节,默认是按4字节对齐,这时就按4字节对齐,所以sizeof(S1)应该为8; zKB$n.H
S2中,c和S1中的a一样,按1字节对齐,而d 是个结构,它是8个字节,它按什么对齐呢?对于结构来说,它的默认对齐方式就是它的所有成员使用的对齐参数中最大的一个,S1的就是4.所以,成员d就是按4字节对齐.成员e是8个字节,它是默认按8字节对齐,和指定的一样,所以它对到8字节的边界上,这时,已经使用了12个字节了,所以又添加了4个字节的空,从第16个字节开始放置成员e.这时,长度为24,已经可以被8(成员e按8字节对齐)整除.这样,一共使用了24个字节. >ENZ['F
a b XlPq>@4p
S1的内存布局:11**,1111, e ?FjN 9
c S1.a S1.b d 33dHTV
S2的内存布局:1***,11**,1111,****11111111 &@CcH_d*
(27bNKr
这里有三点很重要: v7x%V%K
1.每个成员分别按自己的方式对齐,并能最小化长度 ygoA/*s
2.复杂类型(如结构)的默认对齐方式是它最长的成员的对齐方式,这样在成员是复杂类型时,可以最小化长度 Os--@5e
3.对齐后的长度必须是成员中最大的对齐参数的整数倍,这样在处理数组时可以保证每一项都边界对齐 $'#hCs
f& P'Kxj_
0Z9>%\km_
网友xue23(xue23) 的答案和分析: Vx$ ?)&
<7-:flQz~
有程序查一下各个变量的内存地址得知: X6I"&yct
各个变量在内存中的位置为 "NR`{1f:O
c***aa** cKt=_4Lf
bbbb**** 7M;7jI/C
dddddddd yO\.dp
测试代码为: -\C;2&(
s2 ss; 8D3|}z?
cout << "ss.c = " << &ss << endl ; &`+tWL6L
cout << "ss.d.a = " <<&ss.d.a << endl; gXZl3
cout << "ss.d.b = " <<&(ss.d.b) < cout << "ss.d = " <<&ss.e << endl; hKo& ZWPq
print out 各个变量的内存地址不就可以看出来了吗。 pRyePxCDj)
$m{-I=
所以答案是24,2. UXpF$=
\
vf&Ldk
但是我的想像中应该是这样的分布情况: F(+,M~
c******* g{{DC )>
aa**bbbb a=n*}.
dddddddd @I_!q*
%0 cFs'
不知为什么会c和a放在一起,组成8位长度。