Intel和微软同时出现的C语言面试题 '7Q5"M'
#pragma pack(8)
wa7)
ziPE(B
struct s1{ u2}zRC=
short a; 8&+m5xS
long b; sTv;Ogs.
}; %iMRJ}8(7
ruiAEC<Ej
struct s2{ pu3ly&T#a_
char c; :!Ea.v
s1 d; 5'*v-l,[
long long e; d)d\h`=Z
}; {kVhht]X
S &N[@G
#pragma pack() \-i5b
vy&q7EX<i
问 |:Q`9;
1.sizeof(s2) = ? +a7J;-|
2.s2的s1中的a后面空了几个字节接着是b? tgz
)4u6{-|A
AT$eTZ]M
pH!e<m
如果您知道答案请在讨论中写出,以下是部份网友的答案,供参考: e!BablG[
walQo^<
网友rwxybh(行云)的答案: z86[_l:
内存布局是 :jo
!Yi
1*** 11** cVk&Yp;[*
1111 **** _ljdo`j#N
1111 1111 `q":i>FP2
C5k\RS9
所以答案就是24和3 BTi:Bcv k
+OM`c7M:
下面是一个测试的程序,试一试就知道了,我用的是VC2005 EdgcdSb7
]m&cVy&
#pragma pack(8) :70n% 3a
bUJ5jkZ)
struct s1{ fiG/"/u
short a; // 2 BYtes gN./u
long b; // 4 Bytes vMT:j
}; "'i" @CR
struct s2{ H! IL5@@K
char c; // 1 Byte OZ,%T9vP
s1 d; // 8 Bytes {[Sd[P
long long e; // 8 Bytes tw{V7r~n
}; PH$fDbC8
// 1*** 11** $d:>(_p=A
// 1111 **** 3"9'MDKH
// 1111 1111 B}Lz#'5_
// YhpNeP{A
gpt98:w:
// 00 01 02 03 04 05 06 07 2pu8')'P
// 00 01 02 03 04 05 06 07 --X1oC52A
// 00 01 02 03 04 05 06 07 '(N -jk
// ^
hoz<Ns
#pragma pack() P01o: /}
{-FS+D`
int main(int argc, char* argv[]) kWkAfzf4a
{ YTWlR]Tr6?
s2 a; k#*tf:R
char *p = (char *)&a; q].n1w[
for(int i=0;i<24;++i) 4^|;a0Qy]
p = (char)(i%8); &}N=a
printf("%d\n",sizeof(a)); @t W;(8-
printf("c=0x%lx\n",a.c); tp4/c'w;)J
printf("d.a=0x%x\n",a.d.a); ~k}>CNTr
printf("d.b=0x%x\n",a.d.b); |gl~wG1@
printf("e=0x%llx\n",a.e); !+Ia#(
return 0; \:`'!X1*U
} "'M>%m u
结果: @#wBK3Ut^
24 Tno[LP,
c=0x0 1#o><
?
d.a=0x504 MJxTzQE
d.b=0x3020100 *cNqgw#\qL
e=0x706050403020100 XnBpL6"T`
eJh4hp;x
2`|1 !x
网友 redleaves (ID最吊的网友)的答案和分析: }\p>h
">?ocJ\9
如果代码: c(:qid
#pragma pack(8) +1`Zu$|
struct S1{ z@\r V@W5
char a; * &iSW~s
long b; [5KzawV
}; 4s{_(gy
struct S2 { y]z^e\qc)
char c; DBUhqRfl
struct S1 d; <M//zXa
long long e; EqY e.dF,
}; aahAUhF
#pragma pack() .'+*>y!
sizeof(S2)结果为24. m@qM|%(0x
成员对齐有一个重要的条件,即每个成员分别对齐.即每个成员按自己的方式对齐. Km)5;BQxg
也就是说上面虽然指定了按8字节对齐,但并不是所有的成员都是以8字节对齐.其对齐的规则是,每个成员按其类型的对齐参数(通常是这个类型的大小)和指定对齐参数(这里是8字节)中较小的一个对齐.并且结构的长度必须为所用过的所有对齐参数的整数倍,不够就补空字节. N;)Y+amg^
}4
p3m]
S1中,成员a是1字节默认按1字节对齐,指定对齐参数为8,这两个值中取1,a按1字节对齐;成员b是4个字节,默认是按4字节对齐,这时就按4字节对齐,所以sizeof(S1)应该为8; Ib$*w)4:
S2中,c和S1中的a一样,按1字节对齐,而d 是个结构,它是8个字节,它按什么对齐呢?对于结构来说,它的默认对齐方式就是它的所有成员使用的对齐参数中最大的一个,S1的就是4.所以,成员d就是按4字节对齐.成员e是8个字节,它是默认按8字节对齐,和指定的一样,所以它对到8字节的边界上,这时,已经使用了12个字节了,所以又添加了4个字节的空,从第16个字节开始放置成员e.这时,长度为24,已经可以被8(成员e按8字节对齐)整除.这样,一共使用了24个字节. 3M/iuu
a b =x8F!W}Bt<
S1的内存布局:11**,1111, AYB
=iLa
c S1.a S1.b d 8A|{jH74
S2的内存布局:1***,11**,1111,****11111111 0)c9X[sG
C&d%S|:IR
这里有三点很重要: \dIc_6/D1
1.每个成员分别按自己的方式对齐,并能最小化长度 co
<ATx
2.复杂类型(如结构)的默认对齐方式是它最长的成员的对齐方式,这样在成员是复杂类型时,可以最小化长度 ]6PX4oK_t
3.对齐后的长度必须是成员中最大的对齐参数的整数倍,这样在处理数组时可以保证每一项都边界对齐 F0cde
%TO=]>q
ct,Iu+HJ
网友xue23(xue23) 的答案和分析: NS^(5g
iti~RV,
有程序查一下各个变量的内存地址得知: QH_0U`3
各个变量在内存中的位置为 pI__<
c***aa**
l?_h(Cq<
bbbb**** i{['18Q$F3
dddddddd V !Cu%4
测试代码为: z0XH`H|~
s2 ss; ;=&D_jGf]
cout << "ss.c = " << &ss << endl ; TB=KTj
cout << "ss.d.a = " <<&ss.d.a << endl; )kMA_\$,
cout << "ss.d.b = " <<&(ss.d.b) < cout << "ss.d = " <<&ss.e << endl; gnAM}
print out 各个变量的内存地址不就可以看出来了吗。 QFg,pTj
m
6Xex.d
所以答案是24,2. *6Ojv-
G|5
bp'qrcFuiL
但是我的想像中应该是这样的分布情况: xjm|ewo
c******* \,U#^Vr
aa**bbbb f?-=&||f78
dddddddd P>*g'OK^!G
?A!Lh,
不知为什么会c和a放在一起,组成8位长度。