【C語言】21-結構體


說明:這個C語言專題,是學習iOS開發的前奏。也為了讓有面向對象語言開發經驗的程序員,能夠快速上手C語言。如果你還沒有編程經驗,或者對C語言、iOS開發不感興趣,請忽略

C語言的核心部分都說得七七八八了,相信大家已經對C語言的基本數據類型(char\int\float)、數組、指針都很熟悉了,今天來學習C語言中另外一種數據類型:結構體。在iOS開發中,結構體是經常用到的數據類型,使用頻率不亞於指針,所以需要重視,不過用法非常簡單。

一、什么是結構體

* 在第八講的時候已經介紹了C語言中的數組,用法跟其他語言差不多。當一個整體由多個數據構成時,我們可以用數組來表示這個整體,但是數組有個特點:內部的每一個元素都必須是相同類型的數據。

* 在實際應用中,我們通常需要由不同類型的數據來構成一個整體,比如學生這個整體可以由姓名、年齡、身高等數據構成,這些數據都具有不同的類型,姓名可以是字符串類型,年齡可以是整型,身高可以是浮點型。

* 為此,C語言專門提供了一種構造類型來解決上述問題,這就是結構體,它允許內部的元素是不同類型的。

 

二、結構體的定義

1.定義形式

 結構體內部的元素,也就是組成成分,我們一般稱為"成員"。

結構體的一般定義形式為:

 1 struct 結構體名{
 2     
 3     類型名1 成員名1;
 4     
 5     類型名2 成員名2;
 6     
 7     ……
 8     
 9     類型名n 成員名n;   
10     
11 };

struct是關鍵字,是結構體類型的標志。

 

2.舉例

比如,我們定義一個學生

struct Student {
    char *name; // 姓名
    int age; // 年齡
    float height; // 身高
};

上面定義了一個叫做Student的結構體,共有name、age、height3個成員。呵呵,看到這里是否有點面向對象的味道呢,其實這跟面向對象完全是兩碼事,只能說感覺有點像。

 

三、結構體變量的定義

前面只是定義了名字為Student的結構體類型,並非定義了一個結構體變量,就像int一樣,只是一種類型。

接下來定義一個結構體變量,方式有好多種。

1.先定義結構體類型,再定義變量

1 struct Student {
2     char *name;
3     int age;
4 };
5 
6 struct Student stu;

第6行定義了一個結構體變量,變量名為stu。struct和Student是連着使用的。

 

2.定義結構體類型的同時定義變量

struct Student {
    char *name;
    int age;
} stu;

結構體變量名為stu

 

3.直接定義結構體類型變量,省略類型名

struct {
    char *name;
    int age;
} stu;

結構體變量名為stu

 

四、結構體的注意點

1.不允許對結構體本身遞歸定義

如下做法是錯誤,注意第3行

1 struct Student {
2     int age;
3     struct Student stu;
4 };

 

2.結構體內可以包含別的結構體

 1 struct Date {
 2     int year;
 3     int month;
 4     int day;
 5 };
 6 
 7 struct Student {
 8     char *name;
 9     struct Date birthday;
10 };

注意第9行

 

3.定義結構體類型,只是說明了該類型的組成情況,並沒有給它分配存儲空間,就像系統不為int類型本身分配空間一樣。只有當定義屬於結構體類型的變量時,系統才會分配存儲空間給該變量

1 struct Student {
2     char *name;
3     int age;
4 };
5 
6 struct Student stu;

第1~4行並沒有分配存儲空間,當執行到第6行時,系統才會分配存儲空間給stu變量。

 

4.結構體變量占用的內存空間是其成員所占內存之和,而且各成員在內存中按定義的順序依次排列

比如下面的Student結構體:

1 struct Student {
2     char *name; // 姓名
3     int age; // 年齡
4     float height; // 身高
5 };

在16位環境下,一個Student變量共占用內存:2 + 2 + 4 = 8字節。

 

五、結構體的初始化

將各成員的初值,按順序地放在一對大括號{}中,並用逗號分隔,一一對應賦值。

比如初始化Student結構體變量stu

1 struct Student {
2     char *name;
3     int age;
4 };
5 
6 struct Student stu = {"MJ", 27};
只能在定義變量的同時進行初始化賦值,初始化賦值和變量的定義不能分開,下面的做法是錯誤的:
struct Student stu;
stu = {"MJ", 27};

 

六、結構體的使用

1.一般對結構體變量的操作是以成員為單位進行的,引用的一般形式為:結構體變量名.成員名

1 struct Student {
2     char *name;
3     int age;
4 };
5 
6 struct Student stu;
7 
8 // 訪問stu的age成員
9 stu.age = 27;

第9行對結構體的age成員進行了賦值。"."稱為成員運算符,它在所有運算符中優先級最高

 

2.如果某個成員也是結構體變量,可以連續使用成員運算符"."訪問最低一級成員

 1 struct Date {
 2      int year;
 3      int month;
 4      int day;
 5 };
 6 
 7 struct Student {
 8     char *name;
 9     struct Date birthday;
10 };
11 
12 struct Student stu;
13 
14 stu.birthday.year = 1986;
15 stu.birthday.month = 9;
16 stu.birthday.day = 10;

注意第14行以后的代碼

 

3.相同類型的結構體變量之間可以進行整體賦值

 1 struct Student {
 2     char *name;
 3     int age;
 4 };
 5 
 6 struct Student stu1 = {"MJ", 27};
 7 
 8 // 將stu1直接賦值給stu2
 9 struct Student stu2 = stu1;
10 
11 printf("age is %d", stu2.age);

注意第9行。輸出結果為:

 

七、結構體數組

1.定義

跟結構體變量一樣,結構體數組也有3種定義方式

struct Student {
    char *name;
    int age;
};
struct Student stu[5]; //定義1

 

struct Student {
    char *name;
    int age;
} stu[5]; //定義2

 

struct {
    char *name;
    int age;
} stu[5]; //定義3

上面3種方式,都是定義了一個變量名為stu的結構體數組,數組元素個數是5

 

2.初始化

struct {
    char *name;
    int age;
} stu[2] = { {"MJ", 27}, {"JJ", 30} };

也可以用數組下標訪問每一個結構體元素,跟普通數組的用法是一樣的

 

八、結構體作為函數參數

將結構體變量作為函數參數進行傳遞時,其實傳遞的是全部成員的值,也就是將實參中成員的值一一賦值給對應的形參成員。因此,形參的改變不會影響到實參。

 1 #include <stdio.h>
 2 
 3 // 定義一個結構體
 4 struct Student {
 5     int age;
 6 };
 7 
 8 void test(struct Student stu) {
 9     printf("修改前的形參:%d \n", stu.age);
10     // 修改實參中的age
11     stu.age = 10;
12     
13     printf("修改后的形參:%d \n", stu.age);
14 }
15 
16 int main(int argc, const char * argv[]) {
17     
18     struct Student stu = {30};
19     printf("修改前的實參:%d \n", stu.age);
20     
21     // 調用test函數
22     test(stu);
23     
24     
25     printf("修改后的實參:%d \n", stu.age);
26     return 0;
27 }

* 首先在第4行定義了一個結構體類型Student

* 在第18行定義了一個結構體變量stu,並在第22行將其作為實參傳入到test函數

輸出結果為:,形參是改變了,但是實參一直沒有變過

 

九、指向結構體的指針

* 每個結構體變量都有自己的存儲空間和地址,因此指針也可以指向結構體變量

* 結構體指針變量的定義形式:struct 結構體名稱 *指針變量名

* 有了指向結構體的指針,那么就有3種訪問結構體成員的方式

  • 結構體變量名.成員名
  • (*指針變量名).成員名
  • 指針變量名->成員名
 1 #include <stdio.h>
 2 
 3 int main(int argc, const char * argv[]) {
 4     // 定義一個結構體類型
 5     struct Student {
 6         char *name;
 7         int age;
 8     };
 9     
10     // 定義一個結構體變量
11     struct Student stu = {"MJ", 27};
12     
13     // 定義一個指向結構體的指針變量
14     struct Student *p;
15     
16     // 指向結構體變量stu
17     p = &stu;
18 
19     /*
20      這時候可以用3種方式訪問結構體的成員
21      */
22     // 方式1:結構體變量名.成員名
23     printf("name=%s, age = %d \n", stu.name, stu.age);
24     
25     // 方式2:(*指針變量名).成員名
26     printf("name=%s, age = %d \n", (*p).name, (*p).age);
27     
28     // 方式3:指針變量名->成員名
29     printf("name=%s, age = %d \n", p->name, p->age);
30     
31     return 0;
32 }

 輸出結果:


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM