Intel和微软同时出现的C语言面试题 c} GH|i
#pragma pack(8) 6WQT,@?
h7|#7 d
struct s1{ r9Wk7?w)
short a; O$
7R<V
long b; [;/ydE=
}; ShdE!q7
;{79d8/=
struct s2{ tB_GEt2M
char c; f\}fUg2
s1 d; $]eITyC`P
long long e; Gvk)H$ni
}; QQUYWC
V(|@6ww
#pragma pack() ^-9g_5
lU0'5!3R,
问 +wU9d8W
1.sizeof(s2) = ? mjDaus59
2.s2的s1中的a后面空了几个字节接着是b? |?=K'[5
0Z{f!MOh
.mzy?!w0q
P5Y:c@u2
如果您知道答案请在讨论中写出,以下是部份网友的答案,供参考: gwj+~vSfi
o.ntzN
网友rwxybh(行云)的答案: P".CZyI-i
内存布局是 TzT(aWP"
1*** 11** v"VpE`z1#
1111 **** }j^asuf~c
1111 1111 82.::J'e
J|-X?V;ZW
所以答案就是24和3 Z6eM~$Y
N,9W18
@
下面是一个测试的程序,试一试就知道了,我用的是VC2005 nCZ&FNi{O~
5G"DgG*<
#pragma pack(8) x$o?ckyH
2 5DXJb^:
struct s1{ ~ [k0ay
short a; // 2 BYtes 88]V6Rm9[*
long b; // 4 Bytes gJE m
}; J3OxM--8"
struct s2{ ' XJ>;",[
char c; // 1 Byte SW!lSIk
s1 d; // 8 Bytes hSQuML
long long e; // 8 Bytes #)&kF+
}; mhZ{}~
// 1*** 11** 9?5'>WO
// 1111 **** &eL02:[
// 1111 1111 $9!2c /
// ^Oy97Y
?/Bp8q(
// 00 01 02 03 04 05 06 07 )N4!zuSVf
// 00 01 02 03 04 05 06 07 K(
: NshM
// 00 01 02 03 04 05 06 07 ]W^F!p~eC
// 1 !N+hf
#pragma pack() .gL%0
"]1 !<M6\i
int main(int argc, char* argv[]) YIjY?
{ f;AQw_{
s2 a; 9Z.Xo kg
char *p = (char *)&a; V2As 5
for(int i=0;i<24;++i) fhGI
p = (char)(i%8); TPjElBh
printf("%d\n",sizeof(a)); By&T59
printf("c=0x%lx\n",a.c); 'MLp*3djF,
printf("d.a=0x%x\n",a.d.a); dux.Z9X?
printf("d.b=0x%x\n",a.d.b); xeo5)
printf("e=0x%llx\n",a.e); e
:(7$jo
return 0; w;@NYMK)
} cEI
"
结果: ]_!5g3VQh
24 >|{n";n&
c=0x0 e[<vVe!
d.a=0x504 B 2p/
d.b=0x3020100 gEghDO_G
e=0x706050403020100 00jW s@K
>KPxksFR8
g=)B+SY'
网友 redleaves (ID最吊的网友)的答案和分析: vO>Fj
,sw|OYb
如果代码: ;gS)o#v0
#pragma pack(8) Y fRjr
struct S1{ Gw!VPFV>W
char a; sIUhk7Cd8
long b; w ]8+
OP
}; oT76)O
struct S2 { <v&L90+s\;
char c; oeV.K.
struct S1 d; 63'Rw'g^|2
long long e; j) G<PW
}; lZ5LHUzP
#pragma pack() /\L-y,>X
sizeof(S2)结果为24. 6pJFrWe{
成员对齐有一个重要的条件,即每个成员分别对齐.即每个成员按自己的方式对齐. }W2FF
也就是说上面虽然指定了按8字节对齐,但并不是所有的成员都是以8字节对齐.其对齐的规则是,每个成员按其类型的对齐参数(通常是这个类型的大小)和指定对齐参数(这里是8字节)中较小的一个对齐.并且结构的长度必须为所用过的所有对齐参数的整数倍,不够就补空字节. ;Gc,-BDFw
/g/]Q^
S1中,成员a是1字节默认按1字节对齐,指定对齐参数为8,这两个值中取1,a按1字节对齐;成员b是4个字节,默认是按4字节对齐,这时就按4字节对齐,所以sizeof(S1)应该为8; kq| r6uE
S2中,c和S1中的a一样,按1字节对齐,而d 是个结构,它是8个字节,它按什么对齐呢?对于结构来说,它的默认对齐方式就是它的所有成员使用的对齐参数中最大的一个,S1的就是4.所以,成员d就是按4字节对齐.成员e是8个字节,它是默认按8字节对齐,和指定的一样,所以它对到8字节的边界上,这时,已经使用了12个字节了,所以又添加了4个字节的空,从第16个字节开始放置成员e.这时,长度为24,已经可以被8(成员e按8字节对齐)整除.这样,一共使用了24个字节. S2y_5XJ<D
a b tx` Z?K[
S1的内存布局:11**,1111, w)C/EHF
c S1.a S1.b d JRti2Mu
S2的内存布局:1***,11**,1111,****11111111 0m2%ucKw
{5 V@O_*{
这里有三点很重要: |7Dc7p"D
1.每个成员分别按自己的方式对齐,并能最小化长度 QZwUv<*
2.复杂类型(如结构)的默认对齐方式是它最长的成员的对齐方式,这样在成员是复杂类型时,可以最小化长度 eILdq*
3.对齐后的长度必须是成员中最大的对齐参数的整数倍,这样在处理数组时可以保证每一项都边界对齐 tQR qQ
hn`yc7<}(u
vIq>QXb;d
网友xue23(xue23) 的答案和分析: '80mhrEutG
VQ}N&H)`
有程序查一下各个变量的内存地址得知:
}?eO.l{
各个变量在内存中的位置为 |Y-{)5/5}
c***aa** $6[%NQp
bbbb**** 4{PN9i
E
dddddddd ()'yY^
测试代码为: .1{:Q1"S
s2 ss; "A(D}~i
cout << "ss.c = " << &ss << endl ; kAV4V;ydh
cout << "ss.d.a = " <<&ss.d.a << endl; 53X i)
cout << "ss.d.b = " <<&(ss.d.b) < cout << "ss.d = " <<&ss.e << endl; u~O9"-m !V
print out 各个变量的内存地址不就可以看出来了吗。 9%#u,I
Rb/|ae
所以答案是24,2. ^X]rFY1
NqlU?
但是我的想像中应该是这样的分布情况: _xWX/1DY
c******* Ez1-Nx
aa**bbbb ylGT9G19
dddddddd 3VZ}5
14~#k%zO(
不知为什么会c和a放在一起,组成8位长度。