Intel和微软同时出现的C语言面试题 dhsQfWg#}
#pragma pack(8) NC@OmSR\0
R279=sO,J
struct s1{ d,+d8X
short a; >g8Tl`P,iN
long b; *%\z#Bje@
}; |BF4F5wC?
D{ @x
struct s2{ F.^1|+96
char c; >$?$&+e}
s1 d; Z?CmD;W
long long e; q\[f$==p
}; >%'|@75K
/nGsl<
#pragma pack() hJ+>Xm@@!
yH@W6' .
问 I>b!4?h
1.sizeof(s2) = ? ON]
z-
2.s2的s1中的a后面空了几个字节接着是b? #R'm|En'
N1+%[Uh9)
G\|VTqu
gtVI>D'(W
如果您知道答案请在讨论中写出,以下是部份网友的答案,供参考: g' H!%<
8L6!CP_!
网友rwxybh(行云)的答案: %R-"5?eTtu
内存布局是 W32bBzhL
1*** 11** SWPr5h
1111 **** $iupzVrro
1111 1111 Jc(tV(z
yG2j!D
所以答案就是24和3 Z&/bp 1
SA)}---"
下面是一个测试的程序,试一试就知道了,我用的是VC2005 #3\F<AJ<VB
u])N^AY"sj
#pragma pack(8) 50uNgLs
/i"L@t)\t
struct s1{ ~t.*B& A
short a; // 2 BYtes E@Q+[~H }
long b; // 4 Bytes ^MKvZ DOP
}; 9ZeTS~i
struct s2{ ~X*)gS-=
char c; // 1 Byte '8}*erAg
s1 d; // 8 Bytes ja#E}`wC4
long long e; // 8 Bytes W;eHDQ|
}; W`C2zbC
// 1*** 11** '
DCrSa>
// 1111 **** Qpe&_.&RE
// 1111 1111 t'
o:aI
// E5/-?(N
E[)`+:G]
// 00 01 02 03 04 05 06 07 Z Z\,iT
// 00 01 02 03 04 05 06 07 I+kDx=T!
// 00 01 02 03 04 05 06 07 %q`_vtUT
// NoV)}fX$X8
#pragma pack() BD\xUjd?)Q
TmvI+AY/
int main(int argc, char* argv[])
sas;<yh
{ -
b:&ACY
s2 a; #Bj.#5
char *p = (char *)&a; ~?H _?}e
for(int i=0;i<24;++i) ~(~fuDT~O
p = (char)(i%8); =*~]lz__M
printf("%d\n",sizeof(a)); B|/=E470G
printf("c=0x%lx\n",a.c); cX9
!a,
printf("d.a=0x%x\n",a.d.a);
Ma2sQW\
printf("d.b=0x%x\n",a.d.b); p.SEW5
printf("e=0x%llx\n",a.e); &S>m+m'
return 0; nX7{09
} am]$`7R5d
结果: W}50E.\#
24 FrIgu k1
c=0x0 2$V]XSe
d.a=0x504 jn&[=Y-
d.b=0x3020100 yCwBZ/C
e=0x706050403020100 Cdin"
'j 'bhG
{F+7> X
网友 redleaves (ID最吊的网友)的答案和分析: }q^M
`b=?z%LuT
如果代码: W>.KV7
#pragma pack(8) F3HpDfy
struct S1{ /59jkcA+
char a; Gg]>S#^3
long b; $Y5R^Y
}; .J6Oiv.E
struct S2 { qL/4mM0
char c; ^i&sQQ({
struct S1 d; a^hDxeG
long long e; xX.fN7[
}; k1e0kxn
#pragma pack() "94e-Nx
sizeof(S2)结果为24. UA>UW!I
成员对齐有一个重要的条件,即每个成员分别对齐.即每个成员按自己的方式对齐. Mj&q"G
也就是说上面虽然指定了按8字节对齐,但并不是所有的成员都是以8字节对齐.其对齐的规则是,每个成员按其类型的对齐参数(通常是这个类型的大小)和指定对齐参数(这里是8字节)中较小的一个对齐.并且结构的长度必须为所用过的所有对齐参数的整数倍,不够就补空字节. j7IX"O%f\
(C
dx7v2Nh
S1中,成员a是1字节默认按1字节对齐,指定对齐参数为8,这两个值中取1,a按1字节对齐;成员b是4个字节,默认是按4字节对齐,这时就按4字节对齐,所以sizeof(S1)应该为8; s"7wG!yf
S2中,c和S1中的a一样,按1字节对齐,而d 是个结构,它是8个字节,它按什么对齐呢?对于结构来说,它的默认对齐方式就是它的所有成员使用的对齐参数中最大的一个,S1的就是4.所以,成员d就是按4字节对齐.成员e是8个字节,它是默认按8字节对齐,和指定的一样,所以它对到8字节的边界上,这时,已经使用了12个字节了,所以又添加了4个字节的空,从第16个字节开始放置成员e.这时,长度为24,已经可以被8(成员e按8字节对齐)整除.这样,一共使用了24个字节. .]SE>3
a b l}:&}
S1的内存布局:11**,1111, TRW{`b[
c S1.a S1.b d oKLL~X>!U
S2的内存布局:1***,11**,1111,****11111111 %SaC[9=?
j"{|* _6E_
这里有三点很重要: .bE+dA6:v
1.每个成员分别按自己的方式对齐,并能最小化长度 ~Gx"gK0
2.复杂类型(如结构)的默认对齐方式是它最长的成员的对齐方式,这样在成员是复杂类型时,可以最小化长度 fjVGps$j
3.对齐后的长度必须是成员中最大的对齐参数的整数倍,这样在处理数组时可以保证每一项都边界对齐 2R66 WKQ
2Z;wU]
_Q_"_*e
网友xue23(xue23) 的答案和分析: xE`uFHuS}
u(iEuF;7
有程序查一下各个变量的内存地址得知: +F=j1*'&
各个变量在内存中的位置为 `CP#S7W^
c***aa** 9%55R >s$
bbbb**** FR"yGx#$
dddddddd fs_6`Xt
测试代码为: gVO<W.?
s2 ss; =+HMPV6yg7
cout << "ss.c = " << &ss << endl ; wl|cipy"
cout << "ss.d.a = " <<&ss.d.a << endl; A Ch!D>C1
cout << "ss.d.b = " <<&(ss.d.b) < cout << "ss.d = " <<&ss.e << endl; -LI^(_
print out 各个变量的内存地址不就可以看出来了吗。 G;#-CT
BQmHYar
所以答案是24,2. CV&+^_j'k
s
~c_9,JK
但是我的想像中应该是这样的分布情况: FRqJ#yd]
c******* do@`(f3g
aa**bbbb |)`<D
dddddddd MHar9)$}
cBs:7Pnp%
不知为什么会c和a放在一起,组成8位长度。