Intel和微软同时出现的C语言面试题 L*SSv
wSL
#pragma pack(8) mTI\,x%<OC
YI? C-,
struct s1{ 1DI"LIL
short a; <MWXew7b
long b; ~|0F?~eR7
}; T9U2j-lA?
E9Qd>o
struct s2{ D:RBq\8
char c; u+I r:k
s1 d; /w}B07.
long long e; D=q;+,Pc
}; O[5_9W
4
d-#u/{jG)
#pragma pack() '!r+Tz
Jfixm=.6
问 }
Khq
1.sizeof(s2) = ? \h'E5LO
2.s2的s1中的a后面空了几个字节接着是b? |4?}W ,
CLFxq@%nu~
jmk*z(}#:
8R??J>h5\
如果您知道答案请在讨论中写出,以下是部份网友的答案,供参考: avbr7X(
S$kuhK>W!
网友rwxybh(行云)的答案: _L `N^I.
内存布局是 [Q.4]K2
1*** 11** a|6x!p2X
1111 **** Te U7W?M^
1111 1111 %M0mwty]
YKX>@)Dxv
所以答案就是24和3 Wc`J`.#
=|WV^0=S'%
下面是一个测试的程序,试一试就知道了,我用的是VC2005 3A}nNHpN
=p&'_a^$
#pragma pack(8) zb~MF_ &gE
Kt!IyIa;Ht
struct s1{ #.<F5
short a; // 2 BYtes 5M\=+5wB
long b; // 4 Bytes A 4W
}; !7"K>m<
struct s2{ 5qtmb4R~
char c; // 1 Byte EV?47\~
s1 d; // 8 Bytes d;NFkA(df
long long e; // 8 Bytes M~{P',l*
}; s2kZZP8-
// 1*** 11** >fZ/09&3
// 1111 **** \w0b"p
// 1111 1111 k1$2a8ja
// /Vm}+"BCS
(Q+:N;
// 00 01 02 03 04 05 06 07 BHJ'[{U*w
// 00 01 02 03 04 05 06 07 sY;gh`4h
// 00 01 02 03 04 05 06 07 l
SVW}t
// @BHS5^|
#pragma pack()
Sfoy8<j
rM
>V=|9,
int main(int argc, char* argv[]) F#}1{$)%
/
{ N;`[R>Z~
s2 a; K9qEi{[
char *p = (char *)&a; Ignv|TYG
for(int i=0;i<24;++i) i\Q"a B"r
p = (char)(i%8); \gI:`>-
x
printf("%d\n",sizeof(a)); h@m n
GE
printf("c=0x%lx\n",a.c); }fZ=T4r
printf("d.a=0x%x\n",a.d.a); moJT8tb
printf("d.b=0x%x\n",a.d.b); y'2kV6TtqD
printf("e=0x%llx\n",a.e); M6hvi(!X2
return 0; vb"dX0)<
} /4B4IT
结果: N7I71q|
24 1={Tcq\]
c=0x0 4(0t
GF
d.a=0x504 iZq@W3GL
C
d.b=0x3020100 _l{5'm
e=0x706050403020100 R;TEtu7
548[!p4
3P^gP32
网友 redleaves (ID最吊的网友)的答案和分析: )x:j5{>(
tj^:SW.0
如果代码: S_ -QvG2
#pragma pack(8) };|PFWs
struct S1{ 5 *pN<S
char a; ks#Z~6+3
long b; /jn3'q_,
}; 4@mXtA
struct S2 { }
@fu~V/
char c; M+R)P+
struct S1 d; j.'"CU
long long e; \`p~b(
}; cJWfLD>2_!
#pragma pack() .iN*V|n
sizeof(S2)结果为24. wAOVH].
成员对齐有一个重要的条件,即每个成员分别对齐.即每个成员按自己的方式对齐. nM.?Q}yO~
也就是说上面虽然指定了按8字节对齐,但并不是所有的成员都是以8字节对齐.其对齐的规则是,每个成员按其类型的对齐参数(通常是这个类型的大小)和指定对齐参数(这里是8字节)中较小的一个对齐.并且结构的长度必须为所用过的所有对齐参数的整数倍,不够就补空字节. B%g :Z
Nb!6YY=Ez-
S1中,成员a是1字节默认按1字节对齐,指定对齐参数为8,这两个值中取1,a按1字节对齐;成员b是4个字节,默认是按4字节对齐,这时就按4字节对齐,所以sizeof(S1)应该为8; ;7n*PBUJJ
S2中,c和S1中的a一样,按1字节对齐,而d 是个结构,它是8个字节,它按什么对齐呢?对于结构来说,它的默认对齐方式就是它的所有成员使用的对齐参数中最大的一个,S1的就是4.所以,成员d就是按4字节对齐.成员e是8个字节,它是默认按8字节对齐,和指定的一样,所以它对到8字节的边界上,这时,已经使用了12个字节了,所以又添加了4个字节的空,从第16个字节开始放置成员e.这时,长度为24,已经可以被8(成员e按8字节对齐)整除.这样,一共使用了24个字节. Gxa.<E^k
a b BfE-s<
S1的内存布局:11**,1111, -J7,Nw
c S1.a S1.b d c'#J{3d
S2的内存布局:1***,11**,1111,****11111111 "`3^MvC
pOI`,i}.
这里有三点很重要: 6p=x gk-q
1.每个成员分别按自己的方式对齐,并能最小化长度 !4,xQ^
2.复杂类型(如结构)的默认对齐方式是它最长的成员的对齐方式,这样在成员是复杂类型时,可以最小化长度 X>GY*XU
3.对齐后的长度必须是成员中最大的对齐参数的整数倍,这样在处理数组时可以保证每一项都边界对齐 U:4Og8
AUjTcu>i
T!xy^n]}
网友xue23(xue23) 的答案和分析: 3&nc'
[`-O-?=
有程序查一下各个变量的内存地址得知: 8!%"/*P$
各个变量在内存中的位置为 gL}Y5U+s
c***aa** Q.2nUT`
bbbb**** ,Ho.O7H
dddddddd Vv)E41
测试代码为: [O+^eE6h
s2 ss; >\.[}th}
cout << "ss.c = " << &ss << endl ; U8$dG)PhA
cout << "ss.d.a = " <<&ss.d.a << endl; kmr
4cU5
cout << "ss.d.b = " <<&(ss.d.b) < cout << "ss.d = " <<&ss.e << endl; PM<LR?PLc
print out 各个变量的内存地址不就可以看出来了吗。 U4L=3T+:[
sAN:C{
所以答案是24,2. v?TJ!o
g#%FY1xp
但是我的想像中应该是这样的分布情况: %PdYv _5
c******* MVv^KezD
aa**bbbb /^eemx
dddddddd 8Pdnw/W
rHBjR_L.2
不知为什么会c和a放在一起,组成8位长度。