Intel和微软同时出现的C语言面试题 mA@+4&
#pragma pack(8) EZBzQ""
m)}MkC-
struct s1{ id'#s
short a; Kf~+jYobO
long b; {E|gV9g
}; +~O{
UGB=
LP /4e`
struct s2{ fM.|#eLi
char c; k^jCB>b
s1 d; s#ZH.z@J
long long e; IOl"Xgn5
}; 7gcG|kKT
2Zip8f!
#pragma pack() Iq\oB
>~~\==".
问 mM>|fHGA
1.sizeof(s2) = ? 4V8wB}y7e
2.s2的s1中的a后面空了几个字节接着是b? pr(\?\a
taaAwTtk?A
DU8LU*q'
S
'+"+%^tj
如果您知道答案请在讨论中写出,以下是部份网友的答案,供参考: k1zt|
]5/U}Um
网友rwxybh(行云)的答案: GJPZ[bo
内存布局是 qCN7i&k,
1*** 11** ulJYJ+CC!
1111 **** e]h'
1111 1111 tb3fz")UC
d.oFlT
所以答案就是24和3 ^iS:mt
vW3Zu B
下面是一个测试的程序,试一试就知道了,我用的是VC2005 }4%)m
\}NWR{=
#pragma pack(8) I=a$1%BzEX
}*
JMc+!9@
struct s1{ a=VT|CX[
short a; // 2 BYtes x`i`]6q
long b; // 4 Bytes S\gP= .G
}; :G/]rDtd
struct s2{ 7g+ ]
char c; // 1 Byte #SNI
dc>9\
s1 d; // 8 Bytes Fg_s'G,`
long long e; // 8 Bytes *PU,Rc()6
}; w[YbL2p
// 1*** 11** 5T#D5Z<m
// 1111 **** >]8.xkQq
// 1111 1111 4LJ}>e
// X{9o8
*V
/j@ `aG(a
// 00 01 02 03 04 05 06 07 !5t 3Y
// 00 01 02 03 04 05 06 07 tdF[2@?+
// 00 01 02 03 04 05 06 07 F:GKnbY
// ~la04wR28
#pragma pack() >Fk`h=Wd
T?{9Z
int main(int argc, char* argv[]) v=-3 ,C
{ Qp&ySU8
s2 a; z}8L}:
char *p = (char *)&a; :=v{inN
for(int i=0;i<24;++i) #q.G_-H4J@
p = (char)(i%8); 6*33k'=;F
printf("%d\n",sizeof(a)); _O9H._E
printf("c=0x%lx\n",a.c); $OoN/^kv
printf("d.a=0x%x\n",a.d.a); ld:alEo
printf("d.b=0x%x\n",a.d.b); ~ O=| v/]
printf("e=0x%llx\n",a.e); )^f
Q@C8
return 0; R9G)X]
} G>>u#>0
结果: =c^=Yvc7U
24 WVK-dBU
c=0x0 l{m~d!w`a
d.a=0x504 MPy][^s!
d.b=0x3020100 E9 q;>)}
e=0x706050403020100 5THS5'
B/kn&^z$|~
K(fLqXE%
网友 redleaves (ID最吊的网友)的答案和分析: g_c)Ts(
bv>lm56
如果代码: jZ,[{Z(N
#pragma pack(8) a;(zH*/XK
struct S1{ JM lhBh
char a; \[I .
long b; $=xQ X
}; ~<OjXuYu
struct S2 { i/~QJ1C
char c; (ul-J4E\O
struct S1 d; %kFELtx
long long e; 1y-lZ}s_
}; aW-o=l@;
#pragma pack() G5y
sizeof(S2)结果为24. cGzYW~K
成员对齐有一个重要的条件,即每个成员分别对齐.即每个成员按自己的方式对齐. nYt\e]3
也就是说上面虽然指定了按8字节对齐,但并不是所有的成员都是以8字节对齐.其对齐的规则是,每个成员按其类型的对齐参数(通常是这个类型的大小)和指定对齐参数(这里是8字节)中较小的一个对齐.并且结构的长度必须为所用过的所有对齐参数的整数倍,不够就补空字节. T&"dBoUq>G
`G0rF\[
S1中,成员a是1字节默认按1字节对齐,指定对齐参数为8,这两个值中取1,a按1字节对齐;成员b是4个字节,默认是按4字节对齐,这时就按4字节对齐,所以sizeof(S1)应该为8; &Ky u@Tt
S2中,c和S1中的a一样,按1字节对齐,而d 是个结构,它是8个字节,它按什么对齐呢?对于结构来说,它的默认对齐方式就是它的所有成员使用的对齐参数中最大的一个,S1的就是4.所以,成员d就是按4字节对齐.成员e是8个字节,它是默认按8字节对齐,和指定的一样,所以它对到8字节的边界上,这时,已经使用了12个字节了,所以又添加了4个字节的空,从第16个字节开始放置成员e.这时,长度为24,已经可以被8(成员e按8字节对齐)整除.这样,一共使用了24个字节. yw*mA1v
a b
&<w[4z\
S1的内存布局:11**,1111, f*T)*R_
c S1.a S1.b d Y(
$Ji12
S2的内存布局:1***,11**,1111,****11111111 @ "{' j
5h|m4)$
这里有三点很重要: U.hERe~X
1.每个成员分别按自己的方式对齐,并能最小化长度 !&a;P,_Fb
2.复杂类型(如结构)的默认对齐方式是它最长的成员的对齐方式,这样在成员是复杂类型时,可以最小化长度 Z]aK'
3.对齐后的长度必须是成员中最大的对齐参数的整数倍,这样在处理数组时可以保证每一项都边界对齐 aq0iNbv@
s@ 20#D
oWx_O-_._
网友xue23(xue23) 的答案和分析: R7B,Q(q2-
:e&n.i^
有程序查一下各个变量的内存地址得知: 5Q$r@&qp
各个变量在内存中的位置为 KM6N'x ^z
c***aa** Y1fy2\<'
bbbb**** 5&?KW)6 Rz
dddddddd (3N"oE.b]
测试代码为: .A*VLF*m
s2 ss; ia^%Wg7
cout << "ss.c = " << &ss << endl ; 5qd_>UHp
cout << "ss.d.a = " <<&ss.d.a << endl; XYb^Cs;
cout << "ss.d.b = " <<&(ss.d.b) < cout << "ss.d = " <<&ss.e << endl; KZrMf77=
print out 各个变量的内存地址不就可以看出来了吗。 '6o`^u>
hEv=T'*,K)
所以答案是24,2. 'wz\tT ^
o=-Vt,2{
但是我的想像中应该是这样的分布情况: b\?7?g
c******* Xb=2/\}|f
aa**bbbb Tf#2"(!
dddddddd 5e#&"sJ.1
8R\>FNk;
不知为什么会c和a放在一起,组成8位长度。