Intel和微软同时出现的C语言面试题 }:: S0l
#pragma pack(8) VxP&j0M>
%0#1t 5g
struct s1{ gOgps:
short a; `[o)<<}
long b; 4'W '}o|{
}; jq'!UN{
HW&%T7
a
struct s2{ &DqE{bBd!
char c; t+oJV+@
s1 d; &`b
"a!
long long e; d0'JC*
}; |6Gm:jV
+q6ydb,
#pragma pack() '`'GK&)
=b;>?dP
问 IH$0)g;s
1.sizeof(s2) = ? y@CHR
2.s2的s1中的a后面空了几个字节接着是b? B?VhIP e
MO;X>D =
e1//4H::t
A!1;}x
如果您知道答案请在讨论中写出,以下是部份网友的答案,供参考: |t$Ma'P
!4] 9!<.k
网友rwxybh(行云)的答案: kyR*D1N&)
内存布局是 jYNrD"n
1*** 11** CctJFcEZ
1111 **** kw2T>
1111 1111 &A#~)i5gF
BL@:!t
所以答案就是24和3 T843":
keRE==(D
下面是一个测试的程序,试一试就知道了,我用的是VC2005 Em[DHfu1Q
04r$>#E
#pragma pack(8) EpQ8a[<-3
`3p~m,
struct s1{ c8Z wr]DF
short a; // 2 BYtes 12Y
long b; // 4 Bytes 1+?^0%AC
}; ;Eu3[[V
struct s2{ 54zlnM$
char c; // 1 Byte q7u'_R,;
s1 d; // 8 Bytes -i-? .:
long long e; // 8 Bytes Z{'i F
}; tTd\|
// 1*** 11** X.`~>`8
// 1111 **** !3T&4t
// 1111 1111 x@8a''
// KZ~*Nz+H2
G
"P4-
// 00 01 02 03 04 05 06 07 f6$b
s+oP
// 00 01 02 03 04 05 06 07 q -8t'7
// 00 01 02 03 04 05 06 07 zbJT&@z
// iR"N13
#pragma pack() \9-"M;R.d
G:g69=x y
int main(int argc, char* argv[]) dz Zb
{ `~eUee3b.~
s2 a; GfC5z n>
char *p = (char *)&a; 6'xsG?{JY
for(int i=0;i<24;++i) N&@}/wzZ
p = (char)(i%8); I%urz!CNE*
printf("%d\n",sizeof(a)); @JdZ5Q
printf("c=0x%lx\n",a.c); m,fAeln
printf("d.a=0x%x\n",a.d.a); -*.-9B~u
printf("d.b=0x%x\n",a.d.b); :6$>_m=i
printf("e=0x%llx\n",a.e); Sp@-p9#
return 0; V59(Z
} eYx Kp!f
结果: tBpC: SG
24 EqI(|bFwy
c=0x0 =-p$jXVW%
d.a=0x504 7g_]mG[6
d.b=0x3020100 P;4w*((} ~
e=0x706050403020100 w&ak"GgV
w3$
b+Br=Fv"T
网友 redleaves (ID最吊的网友)的答案和分析: utr:J
Y))NK'B5
如果代码: J=/5}u_gw
#pragma pack(8) *2jK#9"MP
struct S1{ :%IoM E
char a; 6-O_\Cq8
long b; m# =z7.XrX
}; $ `7^+8vHV
struct S2 { 7 [0L9\xm
char c; sJNFFOz
struct S1 d; rx}r~0i
long long e; GgKEP,O
}; >t7x>_~
#pragma pack() $tl\UH7%2
sizeof(S2)结果为24. '(/7[tJ
成员对齐有一个重要的条件,即每个成员分别对齐.即每个成员按自己的方式对齐. yr,=.?C-
也就是说上面虽然指定了按8字节对齐,但并不是所有的成员都是以8字节对齐.其对齐的规则是,每个成员按其类型的对齐参数(通常是这个类型的大小)和指定对齐参数(这里是8字节)中较小的一个对齐.并且结构的长度必须为所用过的所有对齐参数的整数倍,不够就补空字节. {s;U~!3aY
ElUEteZ
S1中,成员a是1字节默认按1字节对齐,指定对齐参数为8,这两个值中取1,a按1字节对齐;成员b是4个字节,默认是按4字节对齐,这时就按4字节对齐,所以sizeof(S1)应该为8; d^`?ed\1
S2中,c和S1中的a一样,按1字节对齐,而d 是个结构,它是8个字节,它按什么对齐呢?对于结构来说,它的默认对齐方式就是它的所有成员使用的对齐参数中最大的一个,S1的就是4.所以,成员d就是按4字节对齐.成员e是8个字节,它是默认按8字节对齐,和指定的一样,所以它对到8字节的边界上,这时,已经使用了12个字节了,所以又添加了4个字节的空,从第16个字节开始放置成员e.这时,长度为24,已经可以被8(成员e按8字节对齐)整除.这样,一共使用了24个字节. %j7XEh<'
a b @V!r"Bkg.
S1的内存布局:11**,1111, bV"G~3COy
c S1.a S1.b d 5 (A5Y-B
S2的内存布局:1***,11**,1111,****11111111 cph:y
NFv>B>
这里有三点很重要: ^Ox3XC
1.每个成员分别按自己的方式对齐,并能最小化长度 0V?F'<qy
2.复杂类型(如结构)的默认对齐方式是它最长的成员的对齐方式,这样在成员是复杂类型时,可以最小化长度 8g7<KKw
3.对齐后的长度必须是成员中最大的对齐参数的整数倍,这样在处理数组时可以保证每一项都边界对齐 -44l^}_u
=JmT:enV
{p,]oOq\
网友xue23(xue23) 的答案和分析: NF?
vg/{
)+fh-Ui
有程序查一下各个变量的内存地址得知: ZK)%l~J
各个变量在内存中的位置为 33}oO,}t,
c***aa** fum0>tff
bbbb****
Tgl}
dddddddd "^Ybs'-
测试代码为: G+F:99A
s2 ss; -
|gmQG
cout << "ss.c = " << &ss << endl ; 7VP32Eh[
cout << "ss.d.a = " <<&ss.d.a << endl; +]Y,q
w
cout << "ss.d.b = " <<&(ss.d.b) < cout << "ss.d = " <<&ss.e << endl; k!{p7*0
print out 各个变量的内存地址不就可以看出来了吗。 $kQ~d8 O
eY e, r
所以答案是24,2. nl9P,
d
,UuH}E
但是我的想像中应该是这样的分布情况: CJhL)0Cs
c******* 3)RsLI9
aa**bbbb $cZUM}@
dddddddd [pM V?a[
zen*PeIrA^
不知为什么会c和a放在一起,组成8位长度。