Intel和微软同时出现的C语言面试题 'xH^ksb "
#pragma pack(8) C*mVM!D);!
JP8}+
struct s1{ #gbB// <
short a; d-b04Q7DQ
long b; @v2<T1UC
}; EHUx~Q
{ b$"SIg1E
struct s2{ vH+g*A0S<
char c; tA#Pc6zBuC
s1 d; :|;@FkQ
long long e; ^}+\ 52w
}; >._d2.Q'
Uxjc&o
#pragma pack() -leX|U}k
Q]9$dr=Kk0
问 r *K
1.sizeof(s2) = ? !JA;0[;l=
2.s2的s1中的a后面空了几个字节接着是b? Cu7{>"
529b. |
= Pv_,%
Na91K4r#
如果您知道答案请在讨论中写出,以下是部份网友的答案,供参考: `#$}P;W
7IxeSxXH
网友rwxybh(行云)的答案: "0HUaU,e
内存布局是 JY
1*** 11** ~/G)z?+E
1111 **** `=Ip>7T&
1111 1111 )'kpO> _G
_V$'nz#>e
所以答案就是24和3 4<Vi`X7[F
M
FIb-*wT
下面是一个测试的程序,试一试就知道了,我用的是VC2005 cK'g2S
vK!`#W`X
#pragma pack(8) [Vs\r&qL
HJ&P[zV^
struct s1{ [oh06_rB
short a; // 2 BYtes zA5nr`
long b; // 4 Bytes e \Qys<2r
}; !@& 3q|
struct s2{ FW-I|kK.
char c; // 1 Byte J];Sj
s1 d; // 8 Bytes G|,&V0*
long long e; // 8 Bytes -+E.I*st
};
^xHKoOTj[
// 1*** 11** Xc-["y64
// 1111 **** mI8EeMa{
// 1111 1111 `Na()r$T
// "VZ1LVI
aMI;;iL^
// 00 01 02 03 04 05 06 07 LhO\a
// 00 01 02 03 04 05 06 07 8~(xi<"e
// 00 01 02 03 04 05 06 07 ?TA7i b_
// )M0`dy{1
#pragma pack() 5t:Zp\$+`
yX!fj\R
int main(int argc, char* argv[]) == wX.y\.n
{ \dHqCQ
s2 a; m4m-JD|v
char *p = (char *)&a; 58Ibje
for(int i=0;i<24;++i) ?"@Fq2xgB4
p = (char)(i%8); CE3l_[c
printf("%d\n",sizeof(a)); O&?i#@5#
printf("c=0x%lx\n",a.c); O?OAXPK2
printf("d.a=0x%x\n",a.d.a); jq
H)o2"/
printf("d.b=0x%x\n",a.d.b); hJM&rM7
printf("e=0x%llx\n",a.e); L62'Amml
return 0; htB7 j(
} +;W%v7%<
结果: Gj?Zbl <
24 =n,;S W
c=0x0 llZU: bs
d.a=0x504 {($bzT7c
d.b=0x3020100 {L;sF=d
e=0x706050403020100 %*
0GEfl/
v\@qMaPY
5[;[ Te9=S
网友 redleaves (ID最吊的网友)的答案和分析: e_b,{l#
Ii+3yE@c
如果代码: w Q[|D2;
#pragma pack(8) "5N4
of
8
struct S1{ y11^q*}
char a; 1]If<
<
long b; oEX,\@+u
}; i~Tt\UA>
struct S2 { xCZ_x$bk
char c; 4$R!)
struct S1 d; [#GBn0BG)
long long e; 3uYLA4[-B
}; =G}a%)?As\
#pragma pack() [bnu
DS
sizeof(S2)结果为24. \~#\ [r_
成员对齐有一个重要的条件,即每个成员分别对齐.即每个成员按自己的方式对齐. Z8=?Hu
也就是说上面虽然指定了按8字节对齐,但并不是所有的成员都是以8字节对齐.其对齐的规则是,每个成员按其类型的对齐参数(通常是这个类型的大小)和指定对齐参数(这里是8字节)中较小的一个对齐.并且结构的长度必须为所用过的所有对齐参数的整数倍,不够就补空字节. b%lB&}uw}
CzV;{[?~;
S1中,成员a是1字节默认按1字节对齐,指定对齐参数为8,这两个值中取1,a按1字节对齐;成员b是4个字节,默认是按4字节对齐,这时就按4字节对齐,所以sizeof(S1)应该为8;
Fbo"Csn_
S2中,c和S1中的a一样,按1字节对齐,而d 是个结构,它是8个字节,它按什么对齐呢?对于结构来说,它的默认对齐方式就是它的所有成员使用的对齐参数中最大的一个,S1的就是4.所以,成员d就是按4字节对齐.成员e是8个字节,它是默认按8字节对齐,和指定的一样,所以它对到8字节的边界上,这时,已经使用了12个字节了,所以又添加了4个字节的空,从第16个字节开始放置成员e.这时,长度为24,已经可以被8(成员e按8字节对齐)整除.这样,一共使用了24个字节. XKGiw 2
C
a b {v*4mT
S1的内存布局:11**,1111, [<=RsD_q~
c S1.a S1.b d :=Zd)i)3
S2的内存布局:1***,11**,1111,****11111111 .
Z&5TK4I
o'lG9ePM|
这里有三点很重要: `p\%ha!,w
1.每个成员分别按自己的方式对齐,并能最小化长度 uL)MbM]
2.复杂类型(如结构)的默认对齐方式是它最长的成员的对齐方式,这样在成员是复杂类型时,可以最小化长度 1te^dh:Vp
3.对齐后的长度必须是成员中最大的对齐参数的整数倍,这样在处理数组时可以保证每一项都边界对齐 ~ n<|f
_-f LD
PSc=k0D
网友xue23(xue23) 的答案和分析: $R}C(k
;?
CRo'r/G
有程序查一下各个变量的内存地址得知: c^= q(V
各个变量在内存中的位置为 8
o}5QOW
c***aa** =\]gL%N-|
bbbb**** w5z]=dN
dddddddd mRx `G(u:v
测试代码为: 4&NB xe
s2 ss; TzC(YWt
cout << "ss.c = " << &ss << endl ; ,P<I<QYu
cout << "ss.d.a = " <<&ss.d.a << endl; Qb@j8Xa4[
cout << "ss.d.b = " <<&(ss.d.b) < cout << "ss.d = " <<&ss.e << endl; 2- L-=0
print out 各个变量的内存地址不就可以看出来了吗。 #:" ]-u^
#w L(<nE
所以答案是24,2. I0Do%
p+P@I7V
但是我的想像中应该是这样的分布情况: n`=S&oKH
c******* ^U~Er'mT
aa**bbbb 4AhFE@
dddddddd aKMX-?%t4
`G ":y[Q
不知为什么会c和a放在一起,组成8位长度。