Intel和微软同时出现的C语言面试题 OM@z5UP
#pragma pack(8) f{{J_""?&
+\>op,_9I
struct s1{ !H6X%hlk
short a; B}N1}i+
long b; ! 'Hd:oD<
}; FY/F}C,o
&Cr4<V6-q
struct s2{ CH5>u
char c; d8p5a
C+E
s1 d; "Sw raq
long long e; =pnQ?2Og
}; l}D /1~d
gYmO4/c,
#pragma pack() -NA2+].
Z!l]v.S
问 IL"N_ux~w~
1.sizeof(s2) = ?
.P ??N
2.s2的s1中的a后面空了几个字节接着是b? <%=<9~e
U/h@Q\~U
q&LCMnv"P
.k|\xR
如果您知道答案请在讨论中写出,以下是部份网友的答案,供参考: 5>~D3?IAd
^szi[Cj
网友rwxybh(行云)的答案: qtFHA+bO
内存布局是 zqp>Xw
1*** 11** 6Q]JY,+
1111 **** U+!&~C^y
1111 1111 4Ujy_E?^
h]j>S
所以答案就是24和3 &+yoPF
|ZOdfr4uW
下面是一个测试的程序,试一试就知道了,我用的是VC2005 6wZ)GLW[
X<g
}F[Y
#pragma pack(8) mo&9=TaG
o3h>)4
struct s1{ #J
short a; // 2 BYtes Jw{duM;]
long b; // 4 Bytes wGxH
}; j@{dsS:6
struct s2{ er3`ITp:dp
char c; // 1 Byte 6.6?Rp".
s1 d; // 8 Bytes 2)-4?uz~
long long e; // 8 Bytes NnaO!QW%
}; J
:KU~`r
// 1*** 11** h,,B"vPS
// 1111 **** O9AFQ)u
// 1111 1111 s5)y%,E
// tjx|;m7
PM'2zP[*W
// 00 01 02 03 04 05 06 07 `oM'H+
// 00 01 02 03 04 05 06 07 WADEDl&,'
// 00 01 02 03 04 05 06 07 )c532
y
// @3bVjQ`4f
#pragma pack() "akAGa!V+
{@k
, e
int main(int argc, char* argv[]) @ 'U`a4
{ $xjfW/k?M
s2 a; '6L@l
char *p = (char *)&a; =r3g:j/>q
for(int i=0;i<24;++i) L$y~\1-
p = (char)(i%8); _CBMU'V
printf("%d\n",sizeof(a)); </aQ
printf("c=0x%lx\n",a.c); ]EG8+K6
printf("d.a=0x%x\n",a.d.a); ]bYmM@
printf("d.b=0x%x\n",a.d.b); }c>vk
printf("e=0x%llx\n",a.e); D]N)
return 0; k$pND,Ws
} kfZ(:3W$
结果: <2~DI0pp(
24 [8%q@6[
c=0x0 %,zHS?)l
d.a=0x504 Ge^,hAM'
d.b=0x3020100 'pB?
e=0x706050403020100 X8A.ag0Uu
`,4@;j<^@
aIh} j,
网友 redleaves (ID最吊的网友)的答案和分析: @.`k2lxGd~
u!
dx+v d
如果代码: |nGv:= H@
#pragma pack(8) rmr :G
struct S1{ yB 'C9wEH
char a; ;'
H\s
long b; hMUUnr"8;i
}; H({m1v ~R
struct S2 { ,s2C)bb-
char c; +;M 5Sp
struct S1 d; 1GB]Yi[>
long long e; u]i%<Yy89
}; k!'+7K.
#pragma pack() o2q-x2uB
sizeof(S2)结果为24. 7>0u
N|
成员对齐有一个重要的条件,即每个成员分别对齐.即每个成员按自己的方式对齐. _x^rHADp
也就是说上面虽然指定了按8字节对齐,但并不是所有的成员都是以8字节对齐.其对齐的规则是,每个成员按其类型的对齐参数(通常是这个类型的大小)和指定对齐参数(这里是8字节)中较小的一个对齐.并且结构的长度必须为所用过的所有对齐参数的整数倍,不够就补空字节. I5`>XfO)
bbDm6,
S1中,成员a是1字节默认按1字节对齐,指定对齐参数为8,这两个值中取1,a按1字节对齐;成员b是4个字节,默认是按4字节对齐,这时就按4字节对齐,所以sizeof(S1)应该为8; VT=gb/W6)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个字节. w0vsdM;G
a b w.#z>4#3-
S1的内存布局:11**,1111, k8%@PC$
c S1.a S1.b d DsbTx.vA
S2的内存布局:1***,11**,1111,****11111111 VJ_fA}U
P ?nk>
这里有三点很重要: (U
4n} J
1.每个成员分别按自己的方式对齐,并能最小化长度 gGx(mX._L?
2.复杂类型(如结构)的默认对齐方式是它最长的成员的对齐方式,这样在成员是复杂类型时,可以最小化长度 1&<o3)L:
3.对齐后的长度必须是成员中最大的对齐参数的整数倍,这样在处理数组时可以保证每一项都边界对齐 .yFO]
r1aL
\u))1zRd
3d4A~!Iz
网友xue23(xue23) 的答案和分析: T<NOLfk66
bf{_U%`
有程序查一下各个变量的内存地址得知: LsaX
HI/?b
各个变量在内存中的位置为 Lo5pn
c***aa** $)BPtGMGo
bbbb**** NJV kn~<
dddddddd J9DI(`
测试代码为: -Dy<B
s2 ss; LZ.Xcy
cout << "ss.c = " << &ss << endl ; u3E =r
cout << "ss.d.a = " <<&ss.d.a << endl; `%"x'B`mM
cout << "ss.d.b = " <<&(ss.d.b) < cout << "ss.d = " <<&ss.e << endl; ,v#n\LD`
print out 各个变量的内存地址不就可以看出来了吗。 K<`W>2"
)+=Kh$VbS
所以答案是24,2. 7Z<GlNv
sUK|*y
但是我的想像中应该是这样的分布情况: |5X59!
JL
c******* Aq$1#1J
aa**bbbb ('$*QC.M
dddddddd C=v+e%)x@
"Z;({a$v
不知为什么会c和a放在一起,组成8位长度。