Intel和微软同时出现的C语言面试题 }@avGt;v
#pragma pack(8) 6xAR:
B3-;]6
struct s1{ DXc3u^
L
short a; dMjAG7U
long b; qo62!q
}; M_EXA _
E6mwvrm8
struct s2{ J:JkX>n%k=
char c; "I)`gy&
s1 d; MPF;P&6
long long e; zd^QG
}; .m_-L
Y-
|)IS[:X
#pragma pack() [SX>b"L
Hv.nO-c
问 KL6FmL)HH
1.sizeof(s2) = ? 9|9Hk1
2.s2的s1中的a后面空了几个字节接着是b? {8Uk]
kPg| o3H
s'^"s_j
c&n.JV
如果您知道答案请在讨论中写出,以下是部份网友的答案,供参考: '}.Z' %;
!pG_MO
网友rwxybh(行云)的答案: x cA5
内存布局是 xix:=
a
1*** 11** QeZK&^W
1111 **** v35=4>Y
1111 1111 Ht!]%
S1oP_A[|
所以答案就是24和3 95^A !
[
#1<W`95
下面是一个测试的程序,试一试就知道了,我用的是VC2005 'Z=8no`<
y0f"UH/
#pragma pack(8) yJGM"$
UgjY
struct s1{ *='J>z.]
short a; // 2 BYtes WwBs_OMc
long b; // 4 Bytes z~y=(T
}; :q,tmk h
struct s2{ gS$?#!f
char c; // 1 Byte N#"(
s1 d; // 8 Bytes UjrML
long long e; // 8 Bytes YqSkz|o}m
}; -k I;yL
// 1*** 11** U" ;8zplU
// 1111 **** ,ThN/GkSC
// 1111 1111 7lYiu fg
// G>yTv`-
:Lze8oY(D}
// 00 01 02 03 04 05 06 07 zxffjz,Fe:
// 00 01 02 03 04 05 06 07 oz[:
T3oE>
// 00 01 02 03 04 05 06 07 POtwT">z
// 6o!Y^^/U
#pragma pack() V'jvI
5fqQ;r
int main(int argc, char* argv[]) ]E!b&
{ /a:sWmxMT
s2 a; sp'f>F2]
char *p = (char *)&a; d iG kwKj
for(int i=0;i<24;++i) 236,o
{9e
p = (char)(i%8); 8%W(",nd
printf("%d\n",sizeof(a)); 1 /dy@'
printf("c=0x%lx\n",a.c); "ABg,^jf
printf("d.a=0x%x\n",a.d.a); ir/-zp_
printf("d.b=0x%x\n",a.d.b); (^4V]N&
printf("e=0x%llx\n",a.e); heN?lmC
return 0; u eD_<KjE=
} 4itadQS
结果: Q"2J2211
24 9pJk.Np0
c=0x0 r[}5<S Q
d.a=0x504 JNZ O7s
d.b=0x3020100 mM6X0aM
e=0x706050403020100 <+\
w .!
M!j: 2dT"
B(TE?[ #
网友 redleaves (ID最吊的网友)的答案和分析: #2qDn^s
oYn|>`+6:y
如果代码: CV
)v6f
#pragma pack(8) VA^yv1We
struct S1{ [@LA<Z_
char a; N=[# "4I
long b; }2nmfm!
}; X zF-g*e
struct S2 { k9Xv@v
char c; F&= X/
struct S1 d; wq@{85
long long e; _)U[c;^6
}; U&}v1wdZ3
#pragma pack() VQ,;~^Td
sizeof(S2)结果为24. 8n1<nS<
成员对齐有一个重要的条件,即每个成员分别对齐.即每个成员按自己的方式对齐. Pv3rDQ/Yt|
也就是说上面虽然指定了按8字节对齐,但并不是所有的成员都是以8字节对齐.其对齐的规则是,每个成员按其类型的对齐参数(通常是这个类型的大小)和指定对齐参数(这里是8字节)中较小的一个对齐.并且结构的长度必须为所用过的所有对齐参数的整数倍,不够就补空字节. lI"~*"c`
2LqJ.HH
S1中,成员a是1字节默认按1字节对齐,指定对齐参数为8,这两个值中取1,a按1字节对齐;成员b是4个字节,默认是按4字节对齐,这时就按4字节对齐,所以sizeof(S1)应该为8; B
!}/4"
S2中,c和S1中的a一样,按1字节对齐,而d 是个结构,它是8个字节,它按什么对齐呢?对于结构来说,它的默认对齐方式就是它的所有成员使用的对齐参数中最大的一个,S1的就是4.所以,成员d就是按4字节对齐.成员e是8个字节,它是默认按8字节对齐,和指定的一样,所以它对到8字节的边界上,这时,已经使用了12个字节了,所以又添加了4个字节的空,从第16个字节开始放置成员e.这时,长度为24,已经可以被8(成员e按8字节对齐)整除.这样,一共使用了24个字节. \p%,g&^ x
a b @G&2Tbj[`
S1的内存布局:11**,1111, [zv@}@$
c S1.a S1.b d n
9X:s?B/
S2的内存布局:1***,11**,1111,****11111111 PZjK6]N\
`1fNB1c
这里有三点很重要: ZS\~GQbG
1.每个成员分别按自己的方式对齐,并能最小化长度 td"D&1eQ@
2.复杂类型(如结构)的默认对齐方式是它最长的成员的对齐方式,这样在成员是复杂类型时,可以最小化长度 EO:
VH
3.对齐后的长度必须是成员中最大的对齐参数的整数倍,这样在处理数组时可以保证每一项都边界对齐 8,DY0PGP
9J
$"Qt5;6
Q6lC :cB<
网友xue23(xue23) 的答案和分析: aHR&6zj4
rOyKugHe
有程序查一下各个变量的内存地址得知: T}55ZpSC&
各个变量在内存中的位置为 Z;qgB7-M
c***aa** ]8;2Oh
bbbb**** I"5VkeIx
dddddddd ZqK1|/\
rh
测试代码为: {dF_=`.
s2 ss; p}:"@6
cout << "ss.c = " << &ss << endl ; {`>;I
cout << "ss.d.a = " <<&ss.d.a << endl; lK0pr
cout << "ss.d.b = " <<&(ss.d.b) < cout << "ss.d = " <<&ss.e << endl; 3 J!J#
print out 各个变量的内存地址不就可以看出来了吗。 KdTDBC
%c"t`
所以答案是24,2. nA)KRCi
[d^ [Y:I'\
但是我的想像中应该是这样的分布情况: #vs=yR/tn{
c******* dPmtU{E<M
aa**bbbb e_v_y$
dddddddd )@,zG(t5;
qwomc28O
不知为什么会c和a放在一起,组成8位长度。