Intel和微软同时出现的C语言面试题 $/s"It
#pragma pack(8) pdRM%ug
mP&\?
struct s1{ E+i*u
short a; tO{{ci$-T
long b; I4G0!"T+
}; udqrHR5
T8a' 6otc
struct s2{ U@NCN2I
char c; c 9f"5~
s1 d; GZ~Tl0U
long long e; V*b/N
}; 84QOW|1
ekvs3a^
#pragma pack() v1 8<~
):'wxIVGI
问 A:< %>
1.sizeof(s2) = ? 3A!a7]fW
2.s2的s1中的a后面空了几个字节接着是b? (p{%]M
fgd2jr3T
n7fhc*}:`
IqYJ
如果您知道答案请在讨论中写出,以下是部份网友的答案,供参考: y017
B<Ou
uC;_?Bve
网友rwxybh(行云)的答案: _ l|%~
内存布局是 xT"V9t[f
1*** 11** o6MFMA+vi
1111 **** `.MZ,Xhqi"
1111 1111 bFX{|&tHU
j**[[
所以答案就是24和3 `-uE(qp
#"4ioTL2
下面是一个测试的程序,试一试就知道了,我用的是VC2005 !G-+O#W`
rJ Jx8)M
#pragma pack(8) D!~ Y"4<
RqTO3Kf
struct s1{ i]r(VKX
short a; // 2 BYtes 9,'m,2%W
long b; // 4 Bytes -x+3nb|.
}; D`JBK?~
struct s2{ 3:x(2 A
char c; // 1 Byte RRt(%Wm*
s1 d; // 8 Bytes tLy:F*1i
long long e; // 8 Bytes `MVqd16Y
}; 0 #8
// 1*** 11** 0(7 IsG=t
// 1111 **** \EfX3ghPI
// 1111 1111 j+_fHADq
// ~(V\.hq
8z1z<\
// 00 01 02 03 04 05 06 07 )$n%4 :
// 00 01 02 03 04 05 06 07 rRq60A
// 00 01 02 03 04 05 06 07 ~</FF'Xz
// Bz ;r<Kn
#pragma pack() Dx-P]j)4x
">bhxXeiN
int main(int argc, char* argv[]) X`D2w:
{ {]Zan'{PCO
s2 a; a!$kKOK
char *p = (char *)&a; N[/<xW~x?4
for(int i=0;i<24;++i) (t-hi8"
p = (char)(i%8); X+;[Gc}(W
printf("%d\n",sizeof(a)); \1<'XVS
printf("c=0x%lx\n",a.c); TwkT|Piw
S
printf("d.a=0x%x\n",a.d.a); DO:,PZX
printf("d.b=0x%x\n",a.d.b); DC8#b`j
printf("e=0x%llx\n",a.e); 0#]fEi
return 0; cT'Bp)a
} (GmBv
结果: OMLU ;,4
24 8TP$ ?8l
c=0x0 t*(bF[?
d.a=0x504 w jkh*Y
d.b=0x3020100 L"bJ#0m
e=0x706050403020100 &42]#B"*
lMY\8eobcB
*k LFs|U
网友 redleaves (ID最吊的网友)的答案和分析: qi,) l*?f
~tp]a]yV
如果代码: fB$a)~
#pragma pack(8) rt+4-WuK>
struct S1{ >-MnB
char a; =*\.zr
long b; U?0|2hR~
}; G)7U&B
struct S2 { H~j@n!)
char c; ukR0E4p
struct S1 d; M/<ypJ
long long e; _w\9
\<%
}; f]NLR>$L}
#pragma pack() DsHF9Mn
sizeof(S2)结果为24. VIp|U{
成员对齐有一个重要的条件,即每个成员分别对齐.即每个成员按自己的方式对齐. '##?PQ*u
也就是说上面虽然指定了按8字节对齐,但并不是所有的成员都是以8字节对齐.其对齐的规则是,每个成员按其类型的对齐参数(通常是这个类型的大小)和指定对齐参数(这里是8字节)中较小的一个对齐.并且结构的长度必须为所用过的所有对齐参数的整数倍,不够就补空字节. (kxS0 ]=
Zy(i_B-b
S1中,成员a是1字节默认按1字节对齐,指定对齐参数为8,这两个值中取1,a按1字节对齐;成员b是4个字节,默认是按4字节对齐,这时就按4字节对齐,所以sizeof(S1)应该为8; (K[{X0T
S2中,c和S1中的a一样,按1字节对齐,而d 是个结构,它是8个字节,它按什么对齐呢?对于结构来说,它的默认对齐方式就是它的所有成员使用的对齐参数中最大的一个,S1的就是4.所以,成员d就是按4字节对齐.成员e是8个字节,它是默认按8字节对齐,和指定的一样,所以它对到8字节的边界上,这时,已经使用了12个字节了,所以又添加了4个字节的空,从第16个字节开始放置成员e.这时,长度为24,已经可以被8(成员e按8字节对齐)整除.这样,一共使用了24个字节. J>_mDcPo
a b ^EUR#~b5iy
S1的内存布局:11**,1111, <j'K7We/tP
c S1.a S1.b d V8n {k'
S2的内存布局:1***,11**,1111,****11111111 _5p$#U`
Usf@kVQ
这里有三点很重要: UXct+l
1.每个成员分别按自己的方式对齐,并能最小化长度 7:UeE~uB:
2.复杂类型(如结构)的默认对齐方式是它最长的成员的对齐方式,这样在成员是复杂类型时,可以最小化长度 ,j%\3g`
3.对齐后的长度必须是成员中最大的对齐参数的整数倍,这样在处理数组时可以保证每一项都边界对齐 i<ES/U\
Cv,WG]E7(
*Dp&;, b
网友xue23(xue23) 的答案和分析: ]KFh 1
rp@:i _]
有程序查一下各个变量的内存地址得知: wC{sP"D
各个变量在内存中的位置为 ']nIa7
c***aa** "uBnK!
bbbb**** 1`8s
"T
dddddddd @D9O<x
测试代码为: 7\UHADr
s2 ss; \lK?f] qJq
cout << "ss.c = " << &ss << endl ; _`?0w#>0
cout << "ss.d.a = " <<&ss.d.a << endl; 6(E4l5%
cout << "ss.d.b = " <<&(ss.d.b) < cout << "ss.d = " <<&ss.e << endl; =IL\T8y09
print out 各个变量的内存地址不就可以看出来了吗。 *ra)u-
&y_t,8>5
所以答案是24,2. s@L ;3WdO
Q6(~VvC-
但是我的想像中应该是这样的分布情况: &E`Nu (e
c******* Gpu[<Z4
aa**bbbb 2c Xae
dddddddd %B@NW2ZQ[
R2)@Q
不知为什么会c和a放在一起,组成8位长度。