Intel和微软同时出现的C语言面试题 3>%rm%ffE
#pragma pack(8)
2J
=K\ L
LFob1HH*8
struct s1{ 9D++SU2:}
short a; )f9f_^;
long b; Eym<DPu$n
}; hm >JBc:n-
`uy)][j-
struct s2{ ulV)X/]1
char c; f8kPbpV,
s1 d; .{x-A{l
long long e; 9l9nT
}; uPc}a3'?
zE5%l`@|o
#pragma pack() 9(DS"fgC
Vu0jNKUV
问 C
Fq3
1.sizeof(s2) = ? 4G0Er?D
2.s2的s1中的a后面空了几个字节接着是b? ~YKe:K+&z
bsy\L|wd
tM]~^U
'9%72yG
如果您知道答案请在讨论中写出,以下是部份网友的答案,供参考: R)d1]k8
Bs(\e^}
网友rwxybh(行云)的答案: m!5P5U
x
内存布局是 5v"QKI
1*** 11** YU.aZdA&V3
1111 **** 3JM0 m (
1111 1111 A;n3""
PjNOeI@G
所以答案就是24和3 w~hO)1c],:
B}8xA}<
下面是一个测试的程序,试一试就知道了,我用的是VC2005 &{NN!X
g-"@%ps
#pragma pack(8) x zu)``?
VVO C-:
struct s1{ P:vAU8d>
short a; // 2 BYtes {/G~HoY1i
long b; // 4 Bytes )WavG1
}; 13wO6tS
k
struct s2{ Aq%TZ_m
char c; // 1 Byte __M(dN(^
s1 d; // 8 Bytes +<7~yZ[Z8
long long e; // 8 Bytes u )PB@
}; #4iSQ$0
// 1*** 11** ^JZ ]?iny
// 1111 **** @ofivCc<%
// 1111 1111 .6aC2A]es
// ;`',M6g
<dl:';@a-
// 00 01 02 03 04 05 06 07 6r{NW9y'
// 00 01 02 03 04 05 06 07 ;rZR9fR
// 00 01 02 03 04 05 06 07 OjTb2[Q
// gKoB)n<[
#pragma pack() O4J <u-E$
[E<NEl*
int main(int argc, char* argv[]) m/uBM6SXx
{ >J!4x(;Yh
s2 a; U8Z(=*Z3
char *p = (char *)&a; .1<QB{4~v
for(int i=0;i<24;++i) P}hHx<L
p = (char)(i%8); t=o2:p6&
printf("%d\n",sizeof(a)); &7_xr.c7
printf("c=0x%lx\n",a.c); / r6^]grg
printf("d.a=0x%x\n",a.d.a); _Y@vO
printf("d.b=0x%x\n",a.d.b); W5 ^eCYHoi
printf("e=0x%llx\n",a.e); r:0F("},
return 0; wb~BY
} b>SG5EqU@
结果: l =~EweuM
24 K}7E;O5m"
c=0x0 koDIxj'%X
d.a=0x504 x6Zhw9RV
d.b=0x3020100 1"tyxAo\
e=0x706050403020100 Pj(DlC7G,
ChzKwYDY
C$?gt-tJ'
网友 redleaves (ID最吊的网友)的答案和分析: L!G]i;=:
MJ "ug8N
如果代码: {2"8^;
#pragma pack(8) J=?`~?Vbo
struct S1{ :}(Aq;}X
char a; :_9MS0
long b; &$$KC?!w
}; (%.[MilxPM
struct S2 { L~9Q7 6w
char c; 5hN)y-4@
struct S1 d; [Z~h!}
long long e; Q(v*I&k
};
K|[p4*6
#pragma pack() D>tex/Of3
sizeof(S2)结果为24. ,5}%_
成员对齐有一个重要的条件,即每个成员分别对齐.即每个成员按自己的方式对齐. @p`*MWU
也就是说上面虽然指定了按8字节对齐,但并不是所有的成员都是以8字节对齐.其对齐的规则是,每个成员按其类型的对齐参数(通常是这个类型的大小)和指定对齐参数(这里是8字节)中较小的一个对齐.并且结构的长度必须为所用过的所有对齐参数的整数倍,不够就补空字节. fNR2(8;}
q,S[[{("
S1中,成员a是1字节默认按1字节对齐,指定对齐参数为8,这两个值中取1,a按1字节对齐;成员b是4个字节,默认是按4字节对齐,这时就按4字节对齐,所以sizeof(S1)应该为8; -;]m4R)z
S2中,c和S1中的a一样,按1字节对齐,而d 是个结构,它是8个字节,它按什么对齐呢?对于结构来说,它的默认对齐方式就是它的所有成员使用的对齐参数中最大的一个,S1的就是4.所以,成员d就是按4字节对齐.成员e是8个字节,它是默认按8字节对齐,和指定的一样,所以它对到8字节的边界上,这时,已经使用了12个字节了,所以又添加了4个字节的空,从第16个字节开始放置成员e.这时,长度为24,已经可以被8(成员e按8字节对齐)整除.这样,一共使用了24个字节. KA~eOEjM
a b LF6PKS
S1的内存布局:11**,1111, CVUA7eG+
c S1.a S1.b d ]mIcK
S2的内存布局:1***,11**,1111,****11111111 8i$quHd&x
i/UDda"E
这里有三点很重要: J:W|2U="
1.每个成员分别按自己的方式对齐,并能最小化长度 E%Tpby}^'
2.复杂类型(如结构)的默认对齐方式是它最长的成员的对齐方式,这样在成员是复杂类型时,可以最小化长度 4-j3&(
3.对齐后的长度必须是成员中最大的对齐参数的整数倍,这样在处理数组时可以保证每一项都边界对齐 24{Tl
q3
-DAkVFsN
xib?XzxGo
网友xue23(xue23) 的答案和分析: !@>_5p>q*
Vx'82CIC
有程序查一下各个变量的内存地址得知: :\hcl&W:
各个变量在内存中的位置为 j'L/eps?S
c***aa** P;~`%,+S
bbbb**** v=m!$~
dddddddd jGm`Qg{<
测试代码为: i28WgDG)5
s2 ss; `G/%U~
cout << "ss.c = " << &ss << endl ; aMv?D(Meb
cout << "ss.d.a = " <<&ss.d.a << endl;
2fqg,_
cout << "ss.d.b = " <<&(ss.d.b) < cout << "ss.d = " <<&ss.e << endl; {L6@d1u
print out 各个变量的内存地址不就可以看出来了吗。 b0VEMu81k
Q[PVkZ
所以答案是24,2. 8Dy5g
0FN;^hP5|
但是我的想像中应该是这样的分布情况: tL#~U2K
c******* {"v~1W)
aa**bbbb FZFYwU\~.L
dddddddd QK~44;LVIJ
l<3X:)
不知为什么会c和a放在一起,组成8位长度。