結(jié)構(gòu)與聯(lián)合及函數(shù)_第1頁
結(jié)構(gòu)與聯(lián)合及函數(shù)_第2頁
結(jié)構(gòu)與聯(lián)合及函數(shù)_第3頁
結(jié)構(gòu)與聯(lián)合及函數(shù)_第4頁
結(jié)構(gòu)與聯(lián)合及函數(shù)_第5頁
已閱讀5頁,還剩34頁未讀 繼續(xù)免費(fèi)閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進(jìn)行舉報(bào)或認(rèn)領(lǐng)

文檔簡介

1、1九、聯(lián)合union十、數(shù)據(jù)的引用類型轉(zhuǎn)換十一、位域或位字段第12章 結(jié) 構(gòu) 與 聯(lián) 合 2九、聯(lián)合union1. 聯(lián)合的特性和定義 由關(guān)鍵字struct聲明的數(shù)據(jù)描述稱為結(jié)構(gòu)類型而union 或class聲明的數(shù)據(jù)描述稱為聯(lián)合類型或類類型,分別簡稱為結(jié)構(gòu)和聯(lián)合或類。 結(jié)構(gòu)、聯(lián)合、類是集合數(shù)據(jù)類型。 int、float等是系統(tǒng)預(yù)先取好的可以直接使用的類名,關(guān)鍵字struct和union 或class后緊跟的標(biāo)識符則是用戶引入的類名,需要事先加以聲明。 3 在程序設(shè)計(jì)中常出現(xiàn)非此即彼的數(shù)據(jù),這些數(shù)據(jù)的類型可以不同,需要將其放置在同一片內(nèi)存。 關(guān)鍵字union 建立的數(shù)據(jù)類型為用戶引入的聯(lián)合類型,

2、簡稱聯(lián)合。聯(lián)合一方面是節(jié)省內(nèi)存空間,另一方面是特殊的編程考慮。 聯(lián)合的特性和定義: 聯(lián)合類型定義的變量稱為聯(lián)合變量。指向聯(lián)合變量的指針簡稱為聯(lián)合指針。聯(lián)合類型的聲明和聯(lián)合變量的定義采用與結(jié)構(gòu)類似的語法,不同的是聯(lián)合使用關(guān)鍵字union。 4將前面關(guān)于結(jié)構(gòu)聲明復(fù)制過來略加變動并用union替代struct得到: union UnionName 聯(lián)合 聯(lián)合名 type member; 數(shù)據(jù)類型 成員名 ; type2 member2; 數(shù)據(jù)類型2 成員名2; typen membern; 數(shù)據(jù)類型n 成員名n; ; ; 關(guān)鍵字union用于聲明同一片內(nèi)存可以存放不同類型的數(shù)據(jù),但在一個(gè)時(shí)刻只有某一

3、類型的數(shù)據(jù)處于有效的狀態(tài)。5聯(lián)合類型聲明中的數(shù)據(jù)成員具有如下的性質(zhì): a. 不同的成員占有起始地址相同的內(nèi)存區(qū)域,這些成員以并排的方式重合在一起。 b. 該內(nèi)存區(qū)域的長度確定為所有成員中占有內(nèi)存空間最長的成員所對應(yīng)的長度。 c. 在一個(gè)具體的時(shí)刻僅包含一種數(shù)據(jù)成員有效雖然成員可以是集合型的數(shù)據(jù)。 d. 初始化聯(lián)合變量時(shí)默認(rèn)對第一個(gè)成員進(jìn)行賦值亦僅對一個(gè)成員賦值,初始值的類型屬性應(yīng)與第一個(gè)成員的類型屬性一致,否則編譯器至少給出警告。 e. C+中聯(lián)合不參入繼承機(jī)制即聯(lián)合類既不作基類也不作派生類,不能有虛擬函數(shù)。6例 聯(lián)合的內(nèi)存和結(jié)構(gòu)的內(nèi)存大小比較#include typedef struct s

4、_a double d; char c9; A; typedef struct s_b double d; long k2; B; typedef union u_t A a; B b; U; typedef struct s_t A a; B b; S; void main (void) printf (sizeof(A)= %d, sizeof (A); printf (sizeof(B)= %d,sizeof (B); printf (sizeof(U)= %d, sizeof (U); printf (sizeof(S)= %d, sizeof (S); /輸出:sizeof (A)=

5、 24,sizeof (B)= 16,16, sizeof (U)= 24,24,sizeof (S)= 407 聯(lián)合一經(jīng)聲明就可以定義聯(lián)合變量、聯(lián)合數(shù)組和聯(lián)合指針。 箭頭運(yùn)算符“-”與圓點(diǎn)運(yùn)算符“.”可以用來訪問聯(lián)合中的成員,箭頭運(yùn)算符-的左側(cè)是聯(lián)合指針,圓點(diǎn)操作符.“的左側(cè)是聯(lián)合變量,右側(cè)是聯(lián)合中的成員。 這和結(jié)構(gòu)變量的使用規(guī)則一致。 不同的是結(jié)構(gòu)變量擁有結(jié)構(gòu)中各獨(dú)立的成員所占內(nèi)存之和; 聯(lián)合變量則僅是最大成員所擁有的內(nèi)存,這一片內(nèi)存可由若干類型屬性不同的成員適當(dāng)索引,它們齊頭地占有同一塊內(nèi)存。 8聯(lián)合遵循先聲明后定義再使用的次序。如下所示: typedef union u_t int k

6、4; long member; float y;U; U obj, *pobj; obj.member /聯(lián)合變量名.成員名 pobj-member /聯(lián)合指針名-成員名三個(gè)步驟可以合為一體,再加上初始化格式為: union u_t int k4; long member; float y; b = 1,2,3,4; 初始化只對第一個(gè)聯(lián)合成員進(jìn)行。該凝練的格式聲明一個(gè)名為u_t的聯(lián)合名,其擁有三個(gè)并置的成員,第一個(gè)是int型的數(shù)組成員k4、第二個(gè)是long型的成員member,第三個(gè)是float型的成員y.這三個(gè)成員的內(nèi)存起始地址是一樣的。9例 聯(lián)合指針入口形參和聯(lián)合引用返回 #include

7、 inline int f(int k) return k;typedef union u_t char* s; int (*f)(int); int d; Un ; Un& initial (Un*p ,int n,char * s) switch (n) case 1: p-s=s; break;case 2: p-f=f; break; default: p-d=n; break; /三個(gè)成員互斥地使用同一內(nèi)存 return *p; void main (void) Un x; for (int n=1;n4;n+)10 Un y= initial (&x,n,abcd);switch

8、(n) case 1: printf (%s,%st, x.s,y.s); break; case 2: printf (%d,%dt,x.f(1),y.f(2); break; default: printf (%d, %dn, x. d,y.d); break; /輸出:abcd,abcd1,2 3,3 聯(lián)合變量、聯(lián)合指針和聯(lián)合引用可以作為形參,聯(lián)合變量可以相互賦值。 對聯(lián)合變量的操作需要特別注意成員的類型屬性,不同類型屬性的成員應(yīng)由不同的分支處理。112. 聯(lián)合的內(nèi)存映像考慮如下初始化于一體的聯(lián)合聲明和聯(lián)合變量的定義: union u_t int k4; long z; float y;

9、 b=1,2,3,4,c; 聲明了一個(gè)聯(lián)合名為u_t的聯(lián)合類型,具有三個(gè)成員,這三個(gè)成員是int型數(shù)組k4,long型成員z,float型成員y。 第一個(gè)成員是數(shù)組成員k。同時(shí)定義了兩個(gè)聯(lián)合變量b和c,在定義聯(lián)合變量b的時(shí)候?qū)ζ涞谝粋€(gè)成員進(jìn)行了初始化處理。該聯(lián)合占有的內(nèi)存空間是: sizeof (b)=sizeof (union u)= sizeof (int4)= sizeof (b.k)=1612 該聯(lián)合在32位編程模式下的內(nèi)存布局如下: int型數(shù)組k4 long型成員z 8 12 16 float型成員y 4 聯(lián)合的數(shù)據(jù)內(nèi)存分布 在PC微機(jī)上數(shù)據(jù)的存放方式是低尾端形式的, 即short

10、型16位字節(jié)的低8位存放在內(nèi)存的低地址處, 高8bit存放在內(nèi)存的高地址處高尾端的存放方式則相反。 下頁的例子說明數(shù)據(jù)在PC內(nèi)存中的順序是低尾端形式。k0k1K2K313例 強(qiáng)制類型轉(zhuǎn)換顯示低尾端的存儲格式(8位二進(jìn)制數(shù)的低位在右邊,高位在左邊).#includevoid main() unsigned long m = 0 x87654321UL; unsigned char * p=(unsigned char*)&m;for (int i=0; isizeof (long);i+) printf (%x ,*p+);14 上例低尾端的PC計(jì)算上輸出結(jié)果:21 43 65 87 這樣32位

11、整數(shù)的8個(gè) 4位二進(jìn)制數(shù)的十六進(jìn)制數(shù)數(shù)碼表示為: m= h7h6h5h4h3h2h1h0 =87654321 該數(shù)以字節(jié)即8位bit為最小內(nèi)存尋址單位的內(nèi)存存儲格式為(低地址標(biāo)注在左邊):16進(jìn)制表示: 低地址 高地址 2進(jìn)制表示: 低地址 高地址 21 43 65 87 00100001 01000011 01100101 1000011115 聯(lián)合的同一片內(nèi)存可以通過不同的名稱索引。對一個(gè)成員的改變直接影響聯(lián)合中的其它成員的數(shù)據(jù)狀態(tài),對數(shù)據(jù)的解釋取決于數(shù)據(jù)的存儲格式和模塊轉(zhuǎn)換。例 聯(lián)合的內(nèi)存布局和內(nèi)存數(shù)據(jù)的解釋#include typedef union u_t char c2; unsi

12、gned long k; U;void main() U x = 3,1; /x.c0=3;x.c1=1; 潛在地導(dǎo)致x.c2=0;x.c3=0; printf (%d,0 x%08xt,x.k,x.k); x. k= 0 x67686162UL; printf (%c,%d,%c,%d; ,x.c0,x.c0,x.c1,x.c1); printf (%c,%d,%c,%dn ,x.c2,x.c2,x.c3,x.c3); 16 說明:占4字節(jié)的整型數(shù) (4個(gè)8位的十六進(jìn)制數(shù))存貯格式在微機(jī)上是低尾端格式,具有如下的形式(低地址標(biāo)注在邊,8位二進(jìn)制數(shù)的低位在右邊):高地址 低地址 k= 0 x0

13、000|0103 1*16*16+3=259 x.k= 0 x67686162UL;高地址 低地址 d3 00000000 d2 00000000 d1 00000001 d0 000000011 0 x67 0 x68 0 x61 0 x62c0=3c1=1 c2 c3c00 x62bc10 x61a c2 c317例浮點(diǎn)數(shù)和整型數(shù)內(nèi)存存儲格式不同#include typedef union u_fl float f; long k; Ua; typedef union u_il int f; long k; Ub; struct Sab union float f ; long k; a;

14、 Ub b; s= 1.0,2 ;void main() printf(%1.0f,%dt,s.a.f,s.b.f);Ua & x=(Ua &)s.a ; x.f=10; printf (%d,%dt, (long)(x.f+s.a.f), x.k); x.k=20; printf (%d,%dt, (long)x.f, x.k+s.a.k); Ub & y=s.b ; y.f=10; printf (%d,%dt,(long)y.f,s.b.k); y.k=20; printf (%d,%dn,(long)s.b.f,y.k); /輸出:1,2 20,1092616192 0,40 10,1

15、0 20,20 18 聯(lián)合將不同類型的數(shù)據(jù)鎖定在一塊起始地址相同的內(nèi)存, 通過不同的成員名稱或別名來索引內(nèi)存,以多種方式解釋同一內(nèi)存數(shù)據(jù)。 聯(lián)合具有特殊的數(shù)據(jù)強(qiáng)制類型轉(zhuǎn)換的能力。 注意: union float f ; long k; a; 是聯(lián)合類型直接定義變量,此時(shí)聯(lián)合是無名的。但這種格式不減少訪問內(nèi)層成員的層次 。 193. 無名聯(lián)合 無名聯(lián)合在聲明時(shí)不帶聯(lián)合名,這種聲明在C+語言中具有特殊的含義。 在無名聯(lián)合中定義的名稱超出定界的一對花括號之外,不能跟同一作用范圍其它的變量名沖突,不能有成員函數(shù)。在全局范圍定義的無名聯(lián)合必須聲明為靜態(tài)的,結(jié)構(gòu)中的無名聯(lián)合其成員訪問控制屬性是公共的,不允

16、許存在私有的成員。 a. 局部的和全局的無名聯(lián)合 局部范圍的無名聯(lián)合實(shí)際上定義的是內(nèi)存共享的變量,這些不同類型的變量擁有相同的起始內(nèi)存地址,內(nèi)存數(shù)據(jù)的有效性取決于最新的二進(jìn)制狀態(tài)和對上下文環(huán)境的理解。20例 無名聯(lián)合直接定義局部共享的多個(gè)變量n,m, x, y。 #include void main (void) union int n; long m; double x; double y; ; printf (%p,%pt,&n,&y); n=3; printf (%d,%dt,n,m); x=6; printf (%f,%fn,x,y); /輸出: 0065FDF0,0065FDF0 3

17、,3 6.000000,6.00000021 例 無名聯(lián)合 static union point_t z; point3d b;定義靜態(tài)全局結(jié)構(gòu)變量b和z# include typedef struct double v3; point_t;typedef struct double x,y,z; point3d;typedef union point_t z; point3d b; Ua ;point3d* CrossProduct ( point3d in1, point3d& a) const point3d in2=a;a.x = in1.y * in2.z - in1.z * in2

18、.y;a.y = in1.z * in2.x - in1.x * in2.z;a.z = in1.x * in2.y - in1.y * in2.x;return &a;22static union point_t z; point3d b; ;extern point_t * q;const point3d x=1,1,0;point_t* q;void main(void) b.x=0; b.y=2; b.z=1; q= (point_t*)CrossProduct (x,b); if ( b.x=z.v0 & b.y=z.v1 & b.z=z.v2) printf (b=%4.1f,%4

19、.1f,%4.1ft, b.x, b.y,b.z); printf (q=%4.1f,%4.1f,%4.1ft, q-v0, q-v1, q-v2); Ua a=1,2,3; printf (a=%4.1f,%4.1f,%4.1fn, a.b.x, a.b.y,a.b.z); 23 /輸出: b= 1.0,-1.0, 2.0 q= 1.0,-1.0, 2.0 a= 1.0, 2.0, 3.0 上面的無名聯(lián)合定義靜態(tài)全局結(jié)構(gòu)變量b和z,b和z 是同一片集合內(nèi)存的兩個(gè)別名,相應(yīng)的結(jié)構(gòu)成員也一對一的彼此相配。 兩個(gè)結(jié)構(gòu)本身描述的是空間點(diǎn)的坐標(biāo),只是成員名稱不同;將這樣的結(jié)構(gòu)變量聯(lián)合在一起達(dá)到內(nèi)存數(shù)據(jù)

20、充分共享. 靜態(tài)的全局變量可以通過外部連接屬性的全局指針在不同模塊中傳遞信息。 聯(lián)合可用于接口設(shè)計(jì),兩個(gè)課題組建立了相同的數(shù)據(jù)結(jié)構(gòu)例如 :point_t和point3d,只是其中的成員名稱不同,可以將其聯(lián)合在一起。24b. 結(jié)構(gòu)范圍中的無名聯(lián)合 可以在結(jié)構(gòu)的聲明中引入無名聯(lián)合,無名聯(lián)合包含的數(shù)據(jù)成員在內(nèi)存中共享一片內(nèi)存空間,無名聯(lián)合中單獨(dú)的成員直接作為結(jié)構(gòu)成員的相對獨(dú)立部分。聯(lián)合變量可以作為結(jié)構(gòu)的成員,這相當(dāng)于嵌入的對象,對于嵌入對象需要層層訪問。無名聯(lián)合減少訪問成員的層次,可以直接訪問無名聯(lián)合中的成員。聯(lián)合提供一種課題組之間相同數(shù)據(jù)結(jié)構(gòu)(即成員個(gè)數(shù)、類型、次序相同只是名稱不同)的接口技術(shù)。設(shè)

21、課題組A和B的結(jié)構(gòu)類型為: typedef struct person_a int n; float f; char *s; A; typedef struct person_b int number; float income; char * name; B;25 A結(jié)構(gòu)和B結(jié)構(gòu)是一致的。并在相關(guān)的結(jié)構(gòu)上相應(yīng)地開發(fā)一套算法。將這兩個(gè)結(jié)構(gòu)通過無名聯(lián)合并置在一起,則可以發(fā)揮各自的特點(diǎn)。下面的例子說明無名聯(lián)合的這一用法。例 結(jié)構(gòu)范圍中的無名聯(lián)合實(shí)現(xiàn)不同課題組之間的數(shù)據(jù)接口# include # includetypedef struct a_t union int n; int number; ;

22、 union float f; float income; ; union char *s; char *name; ; A, B; 26 int SeqFind(const B s ,int n,float key) for(int i=0;in;i+) if (si.income=key) return i; return -1; int SeqFind (const A s ,int n,const char* key) for (int i=0;in;i+) if (strcmp(si.s,key)=0) return i; return -1; 27void InitData (B

23、b ,int n ,float f , char (*s)20,int num=5) for(int i=0;inum;i+) bi.number=ni; bi.income=fi; =si; void show (B& r) printf (%d,%f,%st,r.number,r.income,); void show (A* s,int n) for(A*p=s; pn,p-f,p-s); printf (n); 28 const int N=5; static char caN20=Hisen,Boir,Rose,Bush,Kelin; void main(

24、) static int naN=11,22,33,44,55; float xaN=88,90,70,80,60; A sa N; InitData(sa,na,xa,ca,N); show (sa,N); int k=SeqFind (sa,N,Rose); if (k!=-1) show (sak); k=SeqFind (sa,N,60); if (k!=-1) show (sak);29/輸出結(jié)果:11,88.0,Hisen,22,90.0,Boir,33,70.0,Rose,44,80.0,Bush,55,60.0,Kelin,33,70.000000,Rose55,60.0000

25、00,Kelin 聯(lián)合可實(shí)現(xiàn)內(nèi)存的共用與數(shù)據(jù)的共用,更可實(shí)現(xiàn)不同類型數(shù)據(jù)互相排斥地占用同一內(nèi)存或相同內(nèi)存段互異數(shù)據(jù)的不共用。 union在一些介紹C語言的中文書中被譯為共用體,這多少有失union原有的豐富內(nèi)涵。 術(shù)語翻譯應(yīng)切近原意,而其確切含義則需詳細(xì)解釋。30十、數(shù)據(jù)的引用類型轉(zhuǎn)換 基本變量之間存在類型轉(zhuǎn)換關(guān)系。例如: float f; long l=7788; f=(float)l; l=(long)f; 表達(dá)式語句f=(float)l;意味著將long型變量l的值在相應(yīng)的內(nèi)存單元取出,經(jīng)過類型轉(zhuǎn)換模塊,然后將結(jié)果送入f變量表示的存儲單元中,以浮點(diǎn)格式存儲。 對于同類型的結(jié)構(gòu)變量或聯(lián)合變

26、量編譯器允許賦值運(yùn)算。31 設(shè)存在兩個(gè)結(jié)構(gòu)的聲明為: struct sb sb結(jié)構(gòu)數(shù)據(jù)成員列表; ; struct sa sa結(jié)構(gòu)數(shù)據(jù)成員列表; ; 定義結(jié)構(gòu)變量a,a1,b,b1分別如下: struct sa a,a1; struct sb b,b1; a=a1; b=b1; 賦值表達(dá)式語句a=a1表示結(jié)構(gòu)變量a1的數(shù)據(jù)狀態(tài)賦給對應(yīng)的結(jié)構(gòu)變量a,相當(dāng)于系統(tǒng)進(jìn)行了函數(shù)調(diào)用: memcpy (&a,&a1,sizeof(a);32 但不同類型的結(jié)構(gòu)變量的賦值如 a=b1 則是不允許的。 因?yàn)榫幾g器并未提供不同類型結(jié)構(gòu)變量之間賦值的缺省運(yùn)算。同樣對于類型轉(zhuǎn)換: a=(struct s)b1; 系統(tǒng)

27、也會提出錯(cuò)誤警告。系統(tǒng)對于不同結(jié)構(gòu)變量的數(shù)值轉(zhuǎn)換無論是隱含的或顯式都沒有提供缺省的保證。但C+允許引用形式的類型轉(zhuǎn)換。引用形式類型轉(zhuǎn)換的一般形式為: (目標(biāo)類型名&)源變量 (type&)variable引用類型轉(zhuǎn)換的結(jié)果為左值。33 對于兩個(gè)結(jié)構(gòu)變量a,b,一個(gè)具體的引用類型轉(zhuǎn)換的語法格式如下: a = (struct sa&)b; (struct sa&)b = a; 上面兩個(gè)類型轉(zhuǎn)換賦值表達(dá)式可分別理解為: memcpy (&a,&b,sizeof (struct sa); memcpy (&b,&a,sizeof (struct sa); 賦值拷貝映射的原則是將源數(shù)據(jù)內(nèi)存的狀態(tài)根據(jù)目標(biāo)

28、集合的長度復(fù)制給目標(biāo)所占用的內(nèi)存。如果sizeof(sb)大于sizeof(sa),那么轉(zhuǎn)換 b = (sb&)a將導(dǎo)致對集合數(shù)據(jù)a的越界,反之如a = (sa&)b則對長的源數(shù)據(jù)b前面的sizeof(sa)個(gè)元素進(jìn)行了復(fù)制。引用形式類型轉(zhuǎn)換表示了集合數(shù)據(jù)間的直接映射,當(dāng)然也可以對簡單變量進(jìn)行引用的類型轉(zhuǎn)換。34例 結(jié)構(gòu)變量的類型轉(zhuǎn)換與復(fù)制#include typedef struct sa int m; A; typedef struct sb int x; int y; B;void show (B& b) printf (b=%d,%dt,b.x,b.y);void main() A a=1; B b=3,4; (struct sa&)b=a; sh

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論