真实的国产乱ⅩXXX66竹夫人,五月香六月婷婷激情综合,亚洲日本VA一区二区三区,亚洲精品一区二区三区麻豆

成都創(chuàng)新互聯(lián)網(wǎng)站制作重慶分公司

C語(yǔ)言的結(jié)構(gòu)體和共用體怎么使用

今天小編給大家分享一下C語(yǔ)言的結(jié)構(gòu)體和共用體怎么使用的相關(guān)知識(shí)點(diǎn),內(nèi)容詳細(xì),邏輯清晰,相信大部分人都還太了解這方面的知識(shí),所以分享這篇文章給大家參考一下,希望大家閱讀完這篇文章后有所收獲,下面我們一起來(lái)了解一下吧。

創(chuàng)新互聯(lián)公司堅(jiān)持“要么做到,要么別承諾”的工作理念,服務(wù)領(lǐng)域包括:網(wǎng)站設(shè)計(jì)、網(wǎng)站制作、企業(yè)官網(wǎng)、英文網(wǎng)站、手機(jī)端網(wǎng)站、網(wǎng)站推廣等服務(wù),滿足客戶于互聯(lián)網(wǎng)時(shí)代的新建網(wǎng)站設(shè)計(jì)、移動(dòng)媒體設(shè)計(jì)的需求,幫助企業(yè)找到有效的互聯(lián)網(wǎng)解決方案。努力成為您成熟可靠的網(wǎng)絡(luò)建設(shè)合作伙伴!

結(jié)構(gòu)體 / struct

結(jié)構(gòu)體的定義

聲明一個(gè)結(jié)構(gòu)體類型的一般形式為:

struct 結(jié)構(gòu)體名 {      成員列表  };

其中,成員列表中對(duì)各成員都應(yīng)進(jìn)行類型聲明,即:

類型名 成員名;

例如,我們需要在程序中記錄一個(gè)學(xué)生(student)的數(shù)據(jù),包括學(xué)號(hào)(num)、姓名(name)、性別(sex)、年齡(age)、成績(jī)(score)、地址(addr)等

如果要表示圖中的數(shù)據(jù)結(jié)構(gòu),但 C 語(yǔ)言并沒(méi)有提供這種現(xiàn)成的數(shù)據(jù)類型,因此我們需要用定義一種結(jié)構(gòu)體類型來(lái)表示。

truct student {      int num;      char name[20];      char sex;      int age;      float score;      char addr[30];  };

上述定義了一個(gè)新的結(jié)構(gòu)體類型 struct student(注意,struct 是聲明結(jié)構(gòu)體類型時(shí)所必須使用的關(guān)鍵及,不能省略),它向編譯系統(tǒng)聲明,這是一個(gè)“結(jié)構(gòu)體類型”,它包括 num、name、sex、age、score、addr 等不同類型的數(shù)據(jù)項(xiàng)。

應(yīng)當(dāng)說(shuō),這里的 struct student 是一個(gè)類型名,它與系統(tǒng)提供的標(biāo)準(zhǔn)類型(如 int、char、float、double 等)具有同樣的作用,都可以用來(lái)定義變量的類型。

結(jié)構(gòu)體變量

前面只是聲明了一個(gè)結(jié)構(gòu)體類型,它相當(dāng)于一個(gè)模型,但其中并無(wú)具體的數(shù)據(jù),編譯系統(tǒng)對(duì)其也不分配實(shí)際的內(nèi)存單元。為了能在程序中使用結(jié)構(gòu)體類型的數(shù)據(jù),我們應(yīng)當(dāng)定義結(jié)構(gòu)體類型的變量,并在其中存放具體的數(shù)據(jù)。主要以下 3 中方式定義結(jié)構(gòu)體類型變量:

  •  先聲明結(jié)構(gòu)體類型,再定義變量名

結(jié)構(gòu)體類型名 結(jié)構(gòu)體變量名;

例如上面我們已經(jīng)定義了一個(gè)結(jié)構(gòu)體類型 struct student,就可以用它來(lái)聲明變量:

struct student student1, student2;

定義了 student1 和 student2 為 struct student 類型的變量,它們具有 struct student 類型的結(jié)構(gòu),后續(xù)我們可以對(duì)它們進(jìn)行初始化。

  •  在聲明類型的同時(shí)定義變量例如: 

struct student {      int num;      char name[20];      char sex;      int age;      float score;      char addr[30];  } student1, student2;

它的作用與第一種方法相同,即定義了兩個(gè) struct student 類型的變量 student1、student2。這種形式的定義的一般形式為:

struct 結(jié)構(gòu)體名 {      成員列表  } 變量名列表;
  •  直接定義結(jié)構(gòu)體類型變量其省略了結(jié)構(gòu)體名,一般形式為: 

struct {      成員列表  } 變量名列表;

關(guān)于結(jié)構(gòu)體類型,需要補(bǔ)充說(shuō)明一點(diǎn):

類型與變量是不同的概念,不要混淆。我們只能對(duì)變量賦值、存取或運(yùn)算,而不能對(duì)一個(gè)類型進(jìn)行賦值、存取或運(yùn)算。在編譯時(shí),對(duì)類型是不分配空間的,只對(duì)變量分配空間。

簡(jiǎn)單地說(shuō),我們可以把“結(jié)構(gòu)體類型”和“結(jié)構(gòu)體變量”理解為是面向?qū)ο笳Z(yǔ)言中“類”和“對(duì)象”的概念。

此外,結(jié)構(gòu)體里的成員也可以是一個(gè)結(jié)構(gòu)體變量。比如我們先聲明了一個(gè)結(jié)構(gòu)體 struct date:

struct date {      int month;      int day;      int year;  };

然后把它應(yīng)用于聲明 struct student 中:

struct student {      int num;      char name[20];      char sex;      int age;      float score;      struct date birthday;      char addr[30];  } student1, student2;

最后,解釋一個(gè)在閱讀大型開(kāi)源代碼(比如 Objective-C Runtime 源碼)時(shí)容易產(chǎn)生疑問(wèn)的點(diǎn):如下兩個(gè)結(jié)構(gòu)體 SampleA 和 SampleB 聲明的變量在內(nèi)存上其實(shí)是完全一樣的,原因是因?yàn)榻Y(jié)構(gòu)體本身并不帶有任何額外的附加信息:

struct SampleA {      int a;      int b;      int c;  };  struct SampleB {      int a;      struct Part1 {          int b;      };      struct Part2 {          int c;      };  };

結(jié)構(gòu)體變量的引用

引用結(jié)構(gòu)體變量中成員的方式為:

結(jié)構(gòu)體變量名.成員名

例如,student1.num 表示 student1 變量中 num 成員,我們可以對(duì)結(jié)構(gòu)體變量的成員進(jìn)行賦值:student1.num = 10010;。

如果成員本身又屬于一個(gè)結(jié)構(gòu)體類型,則要用若干個(gè)成員運(yùn)算符(點(diǎn)號(hào) .),一級(jí)一級(jí)地找到最低一級(jí)的成員,例如:

student1.birthday.month = 9;

另外對(duì)結(jié)構(gòu)體變量的成員可以像普通變量一樣進(jìn)行各種運(yùn)算,也可以用取址運(yùn)算符 & 引用結(jié)構(gòu)體變量成員的地址,或者引用結(jié)構(gòu)體變量的地址。

結(jié)構(gòu)體變量的初始化

和其他類型變量一樣,對(duì)結(jié)構(gòu)體變量可以在定義時(shí)指定其初始值,用大括號(hào)括起來(lái):

struct student {      int num;      char name[20];      char sex;      int age;      char addr[30];  } a = {10010, "Li Lei", 'M', 18, "Beijing Haidian"};

結(jié)構(gòu)體與數(shù)組

如果一個(gè)數(shù)組的元素為結(jié)構(gòu)體類型,則稱其為“結(jié)構(gòu)體數(shù)組”。結(jié)構(gòu)體數(shù)組與之前介紹的數(shù)值型數(shù)組的不同之處在于每個(gè)數(shù)組元素都是一個(gè)結(jié)構(gòu)體類型的數(shù)據(jù),它們都分別包括各個(gè)成員項(xiàng)。

  •  定義結(jié)構(gòu)體數(shù)組

和定義結(jié)構(gòu)體變量的方法類似,只需聲明其為數(shù)組即可,例如:

struct student {      int num;      char name[20];      char sex;      int age;      float score;      char addr[30];  };  struct student stu[3];

以上定義了一個(gè)數(shù)組 stu,數(shù)組有 3 個(gè)元素,均為 struct student 類型數(shù)據(jù) 

  • 結(jié)構(gòu)體數(shù)組的初始化

與其他類型的數(shù)組一樣,對(duì)結(jié)構(gòu)體數(shù)組可以初始化,例如:

struct student {      int num;      char name[20];      char sex;      int age;      float score;      char addr[30];  } stu[3] = {{10101, "Li Lin", 'M', 18, 87.5, "Beijing"},              {10102, "Amey", 'M', 17,  92, "Shanghai"},              {10103, "Bingo", 'F', 20, 100, "Fujian"}};

從上面可以看到,結(jié)構(gòu)體數(shù)組的初始化的一般形式是在定義數(shù)組的后面加上“={初值表列};”。

結(jié)構(gòu)體數(shù)組中各元素在內(nèi)存中也是連續(xù)存放的,如下圖:

結(jié)構(gòu)體與指針

一個(gè)結(jié)構(gòu)體變量的指針就是該變量所占據(jù)的內(nèi)存段的起始地址??梢栽O(shè)一個(gè)指針變量,用來(lái)指向一個(gè)結(jié)構(gòu)體變量,此時(shí)該指針變量的值是結(jié)構(gòu)體變量的起始地址。指針變量也可以用來(lái)指向結(jié)構(gòu)體數(shù)組中的元素。

  •  指向結(jié)構(gòu)體變量的指針 

struct student {      int num;      char name[20];      char sex;      int age;      float score;      char addr[30];  };  struct student stu1 = {...};  struct student * p;   p = &stu1;

上述代碼先聲明了 struct student 結(jié)構(gòu)體類型,然后定義一個(gè) struct student 類型的變量 stu1,同時(shí)又定義了一個(gè)指針變量 p,它指向一個(gè) struct student 類型的數(shù)據(jù),最后把結(jié)構(gòu)體變量 stu1 的起始地址賦給指針變量 p,如圖所示:

此時(shí)可以用 *p 來(lái)訪問(wèn)結(jié)構(gòu)體變量 stu1 的值,用 (*p).num來(lái)訪問(wèn) stu 的成員變量。C 語(yǔ)言為了使用方便和直觀,定義可以把 (*p).num 改用 p->num 來(lái)代替,它表示 p 所指向的結(jié)構(gòu)體變量中的 num 成員。

也就是說(shuō),以下 3 種形式等價(jià):

  •  結(jié)構(gòu)體變量.成員名:stu1.num

  •  (*指針變量名).成員名:(*p).num

  •  指針變量名->成員名:p->num

  •  指向結(jié)構(gòu)體數(shù)組的指針對(duì)于結(jié)構(gòu)體數(shù)組及其元素也可以用指針變量來(lái)指向,例如: 

struct student {      int num;      char name[20];      char sex;      int age;      float score;      char addr[30];  };  struct student stu[3] = {{10101, "Li Lin", 'M', 18, 87.5, "Beijing"},                           {10102, "Amey", 'M', 17,  92, "Shanghai"},                           {10103, "Bingo", 'F', 20, 100, "Fujian"}};  struct student *p = stu;

此時(shí),指針變量 p 指向數(shù)組首個(gè)元素的地址,即 &stu[0],也就是數(shù)組名 stu。

結(jié)構(gòu)體指針使用場(chǎng)景

(1)函數(shù)參數(shù):用指向結(jié)構(gòu)體變量(或數(shù)組)的指針作實(shí)參,將結(jié)構(gòu)體變量(或數(shù)組)的地址傳給形參。

void printStudentInfo(struct student *p);

因?yàn)槿绻覀冎苯佑媒Y(jié)構(gòu)體變量(不是結(jié)構(gòu)體指針)作為實(shí)參時(shí),由于采取的是“值傳遞”的方式,將結(jié)構(gòu)體變量所占用的內(nèi)存單元的內(nèi)容全部順序傳遞給形參,形參也必須是同類型的結(jié)構(gòu)體變量。

在函數(shù)調(diào)用期間,形參也要占用內(nèi)存單元,這種傳遞方式將帶來(lái)較大的時(shí)間和空間開(kāi)銷,同時(shí)也不利于將在函數(shù)執(zhí)行期間改變形參結(jié)構(gòu)體的值(結(jié)果)返回給主調(diào)函數(shù),因此一般比較少直接“用結(jié)構(gòu)體變量做實(shí)參”,而是改用指針的形式。

(2)鏈表

鏈表是一種常見(jiàn)的且很重要的數(shù)據(jù)結(jié)構(gòu),一般用于動(dòng)態(tài)地進(jìn)行存儲(chǔ)分配。常見(jiàn)的有單鏈表和雙鏈表等,一般可以用結(jié)構(gòu)體來(lái)表示鏈表的節(jié)點(diǎn),如下為常見(jiàn)的“單鏈表”節(jié)點(diǎn)的聲明:

struct ListNode {      int val;      struct ListNode *next;  };

其中,val 表單鏈表節(jié)點(diǎn)的值,next 指針用于指向鏈表的下一個(gè)節(jié)點(diǎn)。

例如,面試比較??疾斓摹胺崔D(zhuǎn)單鏈表”的題目:

struct ListNode *reverseList(struct ListNode *head) {      if (head == NULL) {         return NULL;      }       if (head->next == NULL) {          return head;      }        struct ListNode *reversedHead = NULL;      struct ListNode *prevNode = NULL;      struct ListNode *currentNode = head;        while (currentNode != NULL) {          struct ListNode *nextNode = currentNode->next;          if (nextNode == NULL) {              reversedHead = currentNode;          }                currentNode->next = prevNode;          prevNode = currentNode;          currentNode = nextNode;      }        return reversedHead;  }

(3)二叉樹(shù)

struct TreeNode {      int val;      struct TreeNode *left;      struct TreeNode *right;  };

其中 val 表示二叉樹(shù)葉子節(jié)點(diǎn)的值,left 指向節(jié)點(diǎn)的左子樹(shù),right 指向右子樹(shù)。

例如,之前鬧得沸沸揚(yáng)揚(yáng)的 Google 面試“翻轉(zhuǎn)二叉樹(shù)”的題目:

struct TreeNode *invertTree(struct TreeNode *root) {      if (root == NULL) {          return NULL;      }        root->left = invertTree(root->left);      root->right = invertTree(root->right);         struct TreeNode *temp = root->left;      root->left = root->right;      root->right = temp;        return root;  }

動(dòng)態(tài)開(kāi)辟和釋放內(nèi)存空間

前面介紹,鏈表結(jié)構(gòu)是動(dòng)態(tài)地分配存儲(chǔ)的,即在需要時(shí)才開(kāi)辟一個(gè)節(jié)點(diǎn)的存儲(chǔ)單元。那么,怎樣動(dòng)態(tài)地開(kāi)辟和釋放存儲(chǔ)單元呢?C 語(yǔ)言編譯系統(tǒng)的庫(kù)函數(shù)提供了以下相關(guān)函數(shù)。

  •  malloc 函數(shù)

void * malloc(unsigned size);

其作用是在內(nèi)存的動(dòng)態(tài)存儲(chǔ)區(qū)(堆)中分配一個(gè)長(zhǎng)度為 size 的連續(xù)空間,此函數(shù)的返回值是一個(gè)指向分配域起始地址的指針(類型為 void *,即空指針類型,使用時(shí)可轉(zhuǎn)換為其他指針數(shù)據(jù)類型)。如果此函數(shù)未能成功地執(zhí)行(例如內(nèi)存空間不足時(shí)),則返回空指針 NULL。

使用示例:

int *result = malloc(2 * sizeof(int));  struct ListNode *node = malloc(sizeof(struct ListNode));

上述 result 是一個(gè)分配在堆上的長(zhǎng)度為 2 的數(shù)組,它與 int result[2]; 的區(qū)別是后者分配在內(nèi)存棧區(qū)。而 node 是指向一個(gè) struct ListNode 類型的數(shù)據(jù)(同樣已分配在堆上)的起始地址的指針變量。

  •  calloc 函數(shù)

void * calloc(unsigned n, unsigned size);

其作用是在內(nèi)存的動(dòng)態(tài)存儲(chǔ)區(qū)中分配 n 個(gè)長(zhǎng)度為 size 的連續(xù)空間,函數(shù)返回一個(gè)指向分配域起始地址的指針,如果分配不成功,返回 NULL。

  •  realloc 函數(shù)

void * realloc(void *p, unsigned size);

其作用是將 p 所指向的已分配的動(dòng)態(tài)內(nèi)存區(qū)域的大小重新改為 size,size 可以比原來(lái)分配的空間大或小。該函數(shù)返回指向所分配的內(nèi)存區(qū)起始地址的指針,同樣,如果分配不成功,返回 NULL。

如果傳入的 p 為 NULL,則它的效果和 malloc 函數(shù)相同,即分配 size 字節(jié)的內(nèi)存空間。

如果傳入 size 的值為 0,那么 p 指向的內(nèi)存空間就會(huì)被釋放,但是由于沒(méi)有開(kāi)辟新的內(nèi)存空間,所以會(huì)返回空指針 NULL,類似于調(diào)用 free 函數(shù)。

  •  free 函數(shù)

void free(void *p);

其作用是釋放 p 所指向的內(nèi)存區(qū),使這部分內(nèi)存區(qū)能被其他變量使用,p 一般為調(diào)用上述幾個(gè)函數(shù)返回的值。free 函數(shù)無(wú)返回值。

共用體 / union

有時(shí),我們需要使幾種不同類型的變量存放到同一段內(nèi)存單元中。例如,可以把一個(gè)整型變量(2 個(gè)字節(jié))、一個(gè)字符型變量(1 個(gè)字節(jié))、一個(gè)實(shí)型變量(4 個(gè)字節(jié))放在同一開(kāi)始地址的內(nèi)存單元中,如下圖所示:

以上 3 個(gè)變量在內(nèi)存中占的字節(jié)數(shù)不同,但都從同一地址開(kāi)始存放,也就是幾個(gè)變量相互覆蓋。這種使幾個(gè)不同的變量共占同一段內(nèi)存的結(jié)構(gòu),稱為“共用體”類型的結(jié)構(gòu),也稱為“聯(lián)合體”。

共用體變量的定義

定義共用體類型變量的一般形式為:

union 共用體名 {      成員列表  } 變量

列表;例如:

union data {      int i;      char c;      float f;  } a, b, c;

也可以將類型聲明與變量的定義分開(kāi):

union data {      int i;      char c;      float f;  };  union data a, b, c;

即先聲明一個(gè) union data 類型,再將 a, b, c 定義為 union data 類型。此外,也可以省略共用體名直接定義共用體變量:

union {      int i;      char c;      float f;  } a, b, c;

可以看到,“共用體”與“結(jié)構(gòu)體”的定義形式相似,但它們的含義是不同的:

  •  結(jié)構(gòu)體變量所占的內(nèi)存長(zhǎng)度(字節(jié)總數(shù))是各成員占的內(nèi)存長(zhǎng)度之和,每個(gè)成員都分別獨(dú)占其自己的內(nèi)存單元。

  •  共用體變量所占的內(nèi)存長(zhǎng)度等于最長(zhǎng)的成員的長(zhǎng)度。例如上述定義的共用體變量 a, b, c 各占 4 個(gè)字節(jié)(因?yàn)槠渲凶铋L(zhǎng)的實(shí)型變量占 4 個(gè)字節(jié)),而不是各占 2+1+4=7 個(gè)字節(jié)。

共用體變量的引用

與結(jié)構(gòu)體類似,共用體變量中成員的引用方式為:

共用體變量名.成員名

只有先定義了共用體變量才能引用它,而且不能直接引用共用體變量,只能引用共用體變量中的成員。例如,前面定義了共用體變量 a,則:

  •  a.i 表示引用共用體變量中的整型變量 i

  •  a.c 表示引用共用體變量中的字符型變量 c

  •  a.f 表示引用共用體變量中的實(shí)型變量 f

但不能只引用共用體變量,例如 printf("%d", a); 是錯(cuò)誤的,因?yàn)?a 的存儲(chǔ)區(qū)有好幾種類型,分別占不同長(zhǎng)度的字節(jié),僅寫(xiě)共用體變量名 a,難以使系統(tǒng)確定究竟輸出的哪一個(gè)成員的值。

共用體類型數(shù)據(jù)的特點(diǎn)

在使用共用體類型數(shù)據(jù)時(shí),應(yīng)當(dāng)注意以下一些特點(diǎn):

  •  同一個(gè)內(nèi)存段可以用來(lái)存放幾種不同類型的成員,但在每一瞬時(shí)只能存放其中一種,而不是同時(shí)存放幾種。也就是說(shuō),每一瞬時(shí)只有一個(gè)成員起作用,其它的成員不起作用,即:共用體中的成員不是同時(shí)都存在和起作用的。

  •  共用體變量中起作用的成員是最后一次存放的成員,在存入一個(gè)新的成員后,原有的成員就失去作用了。例如有如下賦值語(yǔ)句: 

a.i = 1;  a.c = 'F';  a.f = 2.5;

在執(zhí)行完以上 3 條賦值語(yǔ)句后,此時(shí)只有 a.f 是有效的,而 a.i 和a.c 已經(jīng)無(wú)意義了。因此在引用共用體變量的成員時(shí),程序員自己必須十分清楚當(dāng)前存放在共用體變量中的究竟是哪個(gè)成員。

  •  共用體變量的地址和它的各成員的地址都是同一地址,例如 &a、&a.i、&a.c、&a.f 都是同一個(gè)地址值,其原因是顯然的。

  •  不能直接對(duì)共用體變量名賦值,也不能企圖引用變量名來(lái)得到一個(gè)值,同時(shí)也不能在定義共用體變量時(shí)對(duì)它初始化。例如,以下這些都是不對(duì)的: 

union {      int i;      char c;      float f;  } a = {1, 'a', 1.5}; // 不能對(duì)共用體初始化  a = 1; // 不能對(duì)共用體變量賦值  m = a; // 不能引用共用體變量名以得到一個(gè)值
  •  不能把共用體變量作為函數(shù)參數(shù),也不能使函數(shù)返回共同體類型的變量,但可以使用指向共用體變量的指針(與結(jié)構(gòu)體變量的指針用法類似,不再贅述)。

  •  共用體類型可以出現(xiàn)在結(jié)構(gòu)體類型定義中,也可以定義共用體數(shù)組。反之,結(jié)構(gòu)體也可以出現(xiàn)在共用體類型定義中,數(shù)組也可以作為共用體的成員。

以上就是“C語(yǔ)言的結(jié)構(gòu)體和共用體怎么使用”這篇文章的所有內(nèi)容,感謝各位的閱讀!相信大家閱讀完這篇文章都有很大的收獲,小編每天都會(huì)為大家更新不同的知識(shí),如果還想學(xué)習(xí)更多的知識(shí),請(qǐng)關(guān)注創(chuàng)新互聯(lián)行業(yè)資訊頻道。


網(wǎng)站名稱:C語(yǔ)言的結(jié)構(gòu)體和共用體怎么使用
文章鏈接:http://weahome.cn/article/picjis.html

其他資訊

在線咨詢

微信咨詢

電話咨詢

028-86922220(工作日)

18980820575(7×24)

提交需求

返回頂部