Intel和微软同时出现的C语言面试题 ~t3?er& R
#pragma pack(8) fU~y481A
Sm_:SF!<D6
struct s1{ ^A<.s_
short a; h=y(2xA
long b; :Du{8rV
}; b`Ek;nYek
9/KQAc*
struct s2{
qhf/B)
char c; <0qY8
s1 d; ]G&\L~P
long long e; l
YA+k5
}; %|* y/m
k#+^=F^)I
#pragma pack() cCKda3v!O
R#bV/7Ol
问 B=/=U7T
1.sizeof(s2) = ? &>4$ [m>n
2.s2的s1中的a后面空了几个字节接着是b? daJ-H
so&3A&4cL
acZ|H
95&sFT
C
如果您知道答案请在讨论中写出,以下是部份网友的答案,供参考: J
2~B<=V
l+X^x%EA
网友rwxybh(行云)的答案: pR7G/]U$A
内存布局是 ct/THq
1*** 11** AG%es0D[H
1111 **** {cHTg04
1111 1111 EMH}VigR
yXl.Gq>]{
所以答案就是24和3 s/^=WV
3lgyX/?o
下面是一个测试的程序,试一试就知道了,我用的是VC2005 h4xdE0
/ ^M3-5@Q
#pragma pack(8) XxQ2g&USk
.shI%'V
struct s1{ Ds5&5&af
short a; // 2 BYtes HY#("=9< h
long b; // 4 Bytes 8(K~QvE~
}; V"p*Jd"w
struct s2{ B>L^XGq
char c; // 1 Byte *4\ub:9
s1 d; // 8 Bytes #!j&L6
long long e; // 8 Bytes sJYX[
}; yf>,oNIAg
// 1*** 11** 1@@]h!>k:
// 1111 **** g+{MvSj$
// 1111 1111 ?UIb!k>
// 1:V/['|*g)
6UP3Ij
// 00 01 02 03 04 05 06 07 UM^hF%
// 00 01 02 03 04 05 06 07 5S?Xl|8E
// 00 01 02 03 04 05 06 07 `b$I)UUm
// -0){C|,6
#pragma pack() *g.,[a0
CA~S$H\"
int main(int argc, char* argv[]) > _) a7%
{ \05C'z3]
s2 a; KA[Su0
char *p = (char *)&a; O4 URr
for(int i=0;i<24;++i) t)b>f~
p = (char)(i%8); iKO~#9OF
printf("%d\n",sizeof(a)); [qo*,CRz
printf("c=0x%lx\n",a.c); ~.SU$
printf("d.a=0x%x\n",a.d.a); nW[aPQ[R
printf("d.b=0x%x\n",a.d.b); +eat,3Ji
printf("e=0x%llx\n",a.e); %tjEVQa
return 0; 2)H|/
} |0Kt@AJY
结果: O3^@" IY
24 O$ \N]#
c=0x0 L(YT6Vmm+t
d.a=0x504 VJPP HJ[-
d.b=0x3020100 <m\TZQBD
e=0x706050403020100 v2SsfhT
S+ x[1#r
U_04QwhK7
网友 redleaves (ID最吊的网友)的答案和分析: A]slssE+
N* QI>kzU
如果代码: 4^A'A.0
#pragma pack(8) !b
Km}1T
struct S1{ <Z wEdq
char a; yw^,@'
long b; _z<q9:
}; Cr"hu;
struct S2 { V!4E(sX
char c; ;">hCM7
struct S1 d; tt OsL')|
long long e; DenCD9 f
}; 8A=(,)`}9
#pragma pack() 6Vo}Uaq4
sizeof(S2)结果为24. 83|/sWrvh
成员对齐有一个重要的条件,即每个成员分别对齐.即每个成员按自己的方式对齐. @ZWKs
也就是说上面虽然指定了按8字节对齐,但并不是所有的成员都是以8字节对齐.其对齐的规则是,每个成员按其类型的对齐参数(通常是这个类型的大小)和指定对齐参数(这里是8字节)中较小的一个对齐.并且结构的长度必须为所用过的所有对齐参数的整数倍,不够就补空字节. /$Jh5Bv
i;7jJ(#V
S1中,成员a是1字节默认按1字节对齐,指定对齐参数为8,这两个值中取1,a按1字节对齐;成员b是4个字节,默认是按4字节对齐,这时就按4字节对齐,所以sizeof(S1)应该为8; l$NEx0Dffz
S2中,c和S1中的a一样,按1字节对齐,而d 是个结构,它是8个字节,它按什么对齐呢?对于结构来说,它的默认对齐方式就是它的所有成员使用的对齐参数中最大的一个,S1的就是4.所以,成员d就是按4字节对齐.成员e是8个字节,它是默认按8字节对齐,和指定的一样,所以它对到8字节的边界上,这时,已经使用了12个字节了,所以又添加了4个字节的空,从第16个字节开始放置成员e.这时,长度为24,已经可以被8(成员e按8字节对齐)整除.这样,一共使用了24个字节. e;v2`2z2
a b {643Dz<e
S1的内存布局:11**,1111, 'McVaPav
c S1.a S1.b d n$K_KU v
S2的内存布局:1***,11**,1111,****11111111 $~l:l[Zs
\>Q,AyL
这里有三点很重要: ZGBcy}U(k
1.每个成员分别按自己的方式对齐,并能最小化长度 +z_0 ?x
2.复杂类型(如结构)的默认对齐方式是它最长的成员的对齐方式,这样在成员是复杂类型时,可以最小化长度 #YV;Gp(2h
3.对齐后的长度必须是成员中最大的对齐参数的整数倍,这样在处理数组时可以保证每一项都边界对齐 P=GM7
/ ffWmb_4
R2{X? 2|$
网友xue23(xue23) 的答案和分析: ""=Vt]
#Ki@=*
有程序查一下各个变量的内存地址得知: n~)%ou
各个变量在内存中的位置为 (TsgVq]L
c***aa** -8:@xG2
bbbb**** 0
$r{h}[^c
dddddddd 5VS<I\o}
测试代码为: R8]bi|e)
s2 ss; xC]/i(+bA
cout << "ss.c = " << &ss << endl ; aeIR}'H|
cout << "ss.d.a = " <<&ss.d.a << endl; x3
<Lx^;
cout << "ss.d.b = " <<&(ss.d.b) < cout << "ss.d = " <<&ss.e << endl; +-i@R%
print out 各个变量的内存地址不就可以看出来了吗。 s4\2lBU?
-u(#V#}OV?
所以答案是24,2. HvU)GJ u b
yCVBG
但是我的想像中应该是这样的分布情况: /6fs h7 \
c******* hvwr!(|W
aa**bbbb )XWL'':bF
dddddddd :8FH{sqR
z%z$'m
不知为什么会c和a放在一起,组成8位长度。