Intel和微软同时出现的C语言面试题 ,Onm!LI=
#pragma pack(8) KQI} 5
PL2Q!i`[o
struct s1{ OX`GN#yl
short a; * =N6_
long b; xRZT
}; tqk6m# @(
`v+O5
struct s2{ {Q3#]Vu
char c; wAwH8x LU
s1 d; i3!$M/_]
long long e; ?At-
}; ?ew]i'9(
*y@]zNPD
#pragma pack() 2\W<EWJ@
ap_+C~%+
问 ^ x#RUv
1.sizeof(s2) = ? KTREOOu .t
2.s2的s1中的a后面空了几个字节接着是b? ^mb*w)-p?
JO$]t|I
|?Uc:VFF
#j5^/*XW
如果您知道答案请在讨论中写出,以下是部份网友的答案,供参考: 5?Ao9Q]@
AxQ/
网友rwxybh(行云)的答案: yodrX&"
内存布局是 OnJSu
z>-
1*** 11** 5~6y.S
1111 **** 9Qd'=JQl
1111 1111 *qOCo_=P8
;a77YLTQ
所以答案就是24和3 eWs^[^c.<
jWCC`0
T
下面是一个测试的程序,试一试就知道了,我用的是VC2005 I>zn$d*0
im\Ws./
#pragma pack(8) s'w0pZqj
7oSuLo=
struct s1{ oW9rl]+
short a; // 2 BYtes gVWLY;c 3}
long b; // 4 Bytes C#cEMKa
}; ,6)y4=8 L
struct s2{ cjpl_}'L:
char c; // 1 Byte .Cd$=v6
s1 d; // 8 Bytes HC}C_Q5c91
long long e; // 8 Bytes +\m!#CSA
}; eW<hC(
// 1*** 11** Sgy~Z^
// 1111 **** JFkjpBS
// 1111 1111 L{Zy7O]"d
// M:M<bz Vu
CK#PxT?"
// 00 01 02 03 04 05 06 07 AYerz
// 00 01 02 03 04 05 06 07 &^>r<~]
// 00 01 02 03 04 05 06 07 >U.uRq
// gQGiph |
#pragma pack() PUo&>
.
2Q/D?a
int main(int argc, char* argv[]) 7K4%`O
{ ,g.=vQm:?
s2 a; h2snGN/{Hb
char *p = (char *)&a; k9?+9bExXA
for(int i=0;i<24;++i) 40ZB;j$l
p = (char)(i%8); c *no H[
printf("%d\n",sizeof(a)); ^ 9E(8DD
printf("c=0x%lx\n",a.c); !(o2K!v0
printf("d.a=0x%x\n",a.d.a); (\
%y)
printf("d.b=0x%x\n",a.d.b); JC3)G/m(03
printf("e=0x%llx\n",a.e); (q7mzZY
return 0; v#G ^W
} $cCB%}
结果: a#$%xw
24 'IszS!kY
c=0x0 [G)Sq;
d.a=0x504 IA!Kpg
W
d.b=0x3020100 EeJ]>
1
e=0x706050403020100 ,iy
k$/].P*!
dy'?@Lj;
网友 redleaves (ID最吊的网友)的答案和分析: B&D
z(Bs
jz0\F,s
如果代码: HDxw2nz*R
#pragma pack(8) &*SnDuc
struct S1{ !ZdUW]
char a; .?
/J
long b; zvj\n9H
}; ~VKXL,.
struct S2 { $T0[
char c; 0:p#%Nvg
struct S1 d; n!nv.-n
long long e; =7>~u
}; egvWPht'_
#pragma pack() [5-5tipvWp
sizeof(S2)结果为24. ?i"FdpW
成员对齐有一个重要的条件,即每个成员分别对齐.即每个成员按自己的方式对齐. pj6Cvq4bD
也就是说上面虽然指定了按8字节对齐,但并不是所有的成员都是以8字节对齐.其对齐的规则是,每个成员按其类型的对齐参数(通常是这个类型的大小)和指定对齐参数(这里是8字节)中较小的一个对齐.并且结构的长度必须为所用过的所有对齐参数的整数倍,不够就补空字节. MIJ~j><L
SqQB>;/p
S1中,成员a是1字节默认按1字节对齐,指定对齐参数为8,这两个值中取1,a按1字节对齐;成员b是4个字节,默认是按4字节对齐,这时就按4字节对齐,所以sizeof(S1)应该为8; I&c#U+-A'
S2中,c和S1中的a一样,按1字节对齐,而d 是个结构,它是8个字节,它按什么对齐呢?对于结构来说,它的默认对齐方式就是它的所有成员使用的对齐参数中最大的一个,S1的就是4.所以,成员d就是按4字节对齐.成员e是8个字节,它是默认按8字节对齐,和指定的一样,所以它对到8字节的边界上,这时,已经使用了12个字节了,所以又添加了4个字节的空,从第16个字节开始放置成员e.这时,长度为24,已经可以被8(成员e按8字节对齐)整除.这样,一共使用了24个字节. on$a]zx'@
a b l|{<!7a
S1的内存布局:11**,1111, v2Y=vr
c S1.a S1.b d ){~.jP=-#
S2的内存布局:1***,11**,1111,****11111111 1g+<`1=KT
V}?5=f'
这里有三点很重要: m~A/.t%=
1.每个成员分别按自己的方式对齐,并能最小化长度 t=#)3C`Q}
2.复杂类型(如结构)的默认对齐方式是它最长的成员的对齐方式,这样在成员是复杂类型时,可以最小化长度 I 3PnyNZ
3.对齐后的长度必须是成员中最大的对齐参数的整数倍,这样在处理数组时可以保证每一项都边界对齐 E83nEUs
Cz%ih#^b
71InYIed
网友xue23(xue23) 的答案和分析: DSp@
cCIEG e6
有程序查一下各个变量的内存地址得知: mLO6`]p{H
各个变量在内存中的位置为 tK*f8X+q
c***aa** ^=j$~*(LmX
bbbb**** lVHJ}(<'p
dddddddd 3IIlAzne;
测试代码为: z7o59&
s2 ss; o-_a0j
cout << "ss.c = " << &ss << endl ; -u{:39y{n
cout << "ss.d.a = " <<&ss.d.a << endl; Z)~2{)
cout << "ss.d.b = " <<&(ss.d.b) < cout << "ss.d = " <<&ss.e << endl; _JS'~JO3{
print out 各个变量的内存地址不就可以看出来了吗。 &V$R@~x
@,vSRns
所以答案是24,2. Yc}b&
\T?O.
但是我的想像中应该是这样的分布情况: ;Xns 9
c******* V'B 6C#jT
aa**bbbb FgxQ}VvlH
dddddddd [sBD|P;M
t$J-6dW
不知为什么会c和a放在一起,组成8位长度。