Intel和微软同时出现的C语言面试题 |PM m?2^ R
#pragma pack(8) lg/sMF>z\f
@oH[SWx
struct s1{ {tzxA_
short a; 8@7AE"
long b; q9}2
}; shi
Hy*(v
>,g5Hkmqr
struct s2{ N
<pbO#e
char c; k0&lu B%
s1 d; l`rC0kJ]
long long e; dm^H5D/A
}; U'3Fou}
}bfn_ G
#pragma pack() *)PG-$6X&
$N.`)S<
问 tjb/[RQ
1.sizeof(s2) = ? aV|k}H{wt
2.s2的s1中的a后面空了几个字节接着是b? Ku%6$C!,
|>sv8/!
?6:cNdN
Fd!iQ
如果您知道答案请在讨论中写出,以下是部份网友的答案,供参考: >rRf9wO1l
H%.zXQ4}n
网友rwxybh(行云)的答案: |[w^eg
内存布局是 ^HFo3V
}h
1*** 11** q,,j',8kq/
1111 **** (UW6F4:$
1111 1111 (
Yi=v'd
^]rxhpS
所以答案就是24和3 u_'nOle
K
G\mKCaI8
下面是一个测试的程序,试一试就知道了,我用的是VC2005 /VtlG+dLl
rdI]\UH
#pragma pack(8) |a(Q4 e/,
p+D=}O
struct s1{ !1-&Y'+
short a; // 2 BYtes 8?Wgawx
long b; // 4 Bytes F^sw0 .b
}; /W9
&Ke
struct s2{ 9[f%;WaS
char c; // 1 Byte >x?2Fz.
s1 d; // 8 Bytes 0 0,9azs
long long e; // 8 Bytes pDhY%w#
}; pU DO7Q]
// 1*** 11** {jG.=}/Dk
// 1111 **** 3jg'1^c
// 1111 1111 SEU\}Ni{
// Z%;)@0~f
r:#Q9EA
// 00 01 02 03 04 05 06 07 ^hysC c
// 00 01 02 03 04 05 06 07 4a 4N
C
// 00 01 02 03 04 05 06 07 D@5s8xv
// Z*h ;e;
#pragma pack() =?+w)(*0c
EJ8I[(
int main(int argc, char* argv[]) mLULd} g/o
{ Ik-oI=>.
s2 a; yI:r7=KO
char *p = (char *)&a; ?to1rFrU
for(int i=0;i<24;++i) 5R"2Wd
p = (char)(i%8); D8EeZUqU
printf("%d\n",sizeof(a)); 7
{nl..`
printf("c=0x%lx\n",a.c); w=5
printf("d.a=0x%x\n",a.d.a); e|~C?Ow'J
printf("d.b=0x%x\n",a.d.b); lJlZHO
printf("e=0x%llx\n",a.e); EM=xd~H
return 0;
>kZ6f 4
} ki`8(u6l
结果: Y[h#hZ
24 S$\.4*_H\
c=0x0 SF"#\{cjj
d.a=0x504 @kz!{g]Sn
d.b=0x3020100 Nr%(2[$ =
e=0x706050403020100 "0b?+ 3_{G
:b<KX%g
<_>.!9q
网友 redleaves (ID最吊的网友)的答案和分析: NWb}
OXK/
v7L"`
如果代码: 487YaioB$
#pragma pack(8) TZ:34\u
struct S1{ yAAG2c4(
char a; rAM*\=
long b; 3;y_qwA
}; LSSW.Oz2L
struct S2 { zuk"
char c; @81-kdTx
struct S1 d; %3rTQ:X
long long e; C1KfXC*|L
}; Z(KmS(
#pragma pack() :4%<Rp
sizeof(S2)结果为24. AfUZO^<
成员对齐有一个重要的条件,即每个成员分别对齐.即每个成员按自己的方式对齐. m"<4\;GK
也就是说上面虽然指定了按8字节对齐,但并不是所有的成员都是以8字节对齐.其对齐的规则是,每个成员按其类型的对齐参数(通常是这个类型的大小)和指定对齐参数(这里是8字节)中较小的一个对齐.并且结构的长度必须为所用过的所有对齐参数的整数倍,不够就补空字节. Q,D0kS P
]7v81G5E
S1中,成员a是1字节默认按1字节对齐,指定对齐参数为8,这两个值中取1,a按1字节对齐;成员b是4个字节,默认是按4字节对齐,这时就按4字节对齐,所以sizeof(S1)应该为8; |O57N'/
S2中,c和S1中的a一样,按1字节对齐,而d 是个结构,它是8个字节,它按什么对齐呢?对于结构来说,它的默认对齐方式就是它的所有成员使用的对齐参数中最大的一个,S1的就是4.所以,成员d就是按4字节对齐.成员e是8个字节,它是默认按8字节对齐,和指定的一样,所以它对到8字节的边界上,这时,已经使用了12个字节了,所以又添加了4个字节的空,从第16个字节开始放置成员e.这时,长度为24,已经可以被8(成员e按8字节对齐)整除.这样,一共使用了24个字节. sfyBw
a b >_-!zjO8u
S1的内存布局:11**,1111, h (qshbC}
c S1.a S1.b d stX'yya
S2的内存布局:1***,11**,1111,****11111111 m dC`W&r
.F4oo =
这里有三点很重要: D!X>O}
1.每个成员分别按自己的方式对齐,并能最小化长度 GhtbQM1[H
2.复杂类型(如结构)的默认对齐方式是它最长的成员的对齐方式,这样在成员是复杂类型时,可以最小化长度 nrF%wH/5
3.对齐后的长度必须是成员中最大的对齐参数的整数倍,这样在处理数组时可以保证每一项都边界对齐 "|F.'qZrm
{cmo^~[L$
&}>|5>cJu
网友xue23(xue23) 的答案和分析: f9vcf# 2
s`;0
t YG
有程序查一下各个变量的内存地址得知: -E6J f$
各个变量在内存中的位置为 #!w:_T%
c***aa** lr`?yn1D(
bbbb**** B{;11u
dddddddd P)Z/JHB
测试代码为: ]#vWKNv:;
s2 ss; 4\&H?:c.
cout << "ss.c = " << &ss << endl ; V/`#B$6
cout << "ss.d.a = " <<&ss.d.a << endl; {`+bW"9
cout << "ss.d.b = " <<&(ss.d.b) < cout << "ss.d = " <<&ss.e << endl; =]!8:I?C<
print out 各个变量的内存地址不就可以看出来了吗。 h~,x7]w6
C]yvK}
所以答案是24,2. Y*`:M(
01&*`0?
但是我的想像中应该是这样的分布情况: 5OPS&:
c******* |}M~kJ)
aa**bbbb 7J0 ^N7"o
dddddddd h |s*i
OI'uH$y
不知为什么会c和a放在一起,组成8位长度。