什么是結(jié)構(gòu)體?
結(jié)構(gòu)體是一種集合褂策,它里面包含了多個變量或數(shù)組,它們的類型可以相同谓苟,也可以不同涕癣,每個這樣的變量或數(shù)組都稱為結(jié)構(gòu)體的成員(Member).
像 int哗蜈、float、char 等是由C語言本身提供的數(shù)據(jù)類型坠韩,不能再進行分拆距潘,我們稱之為基本數(shù)據(jù)類型;而結(jié)構(gòu)體可以包含多個基本類型的數(shù)據(jù)只搁,也可以包含其他的結(jié)構(gòu)體音比,我們將它稱為復(fù)雜數(shù)據(jù)類型或構(gòu)造數(shù)據(jù)類型。
結(jié)構(gòu)體的定義
/**
* 定義一個結(jié)構(gòu)體, 結(jié)構(gòu)體本質(zhì)上也是一種數(shù)據(jù)類型
* 類型是Books的結(jié)構(gòu)體
*/
struct Books {
char title[50];
char *subject;
int book_id;
};
char[] 和 char * 都可以聲明一個字符, 但是是有區(qū)別的, char[] 可以直接操作字符串中的每個字符, 而char * 則不可以.
char[]是數(shù)組, 不是指針, 指針賦值可以使用點的方式或者->.
數(shù)組賦值字符串只能使用strcpy()的方式, char * 則可以直接使用(.)操作符和賦值
結(jié)構(gòu)體變量
// 聲明 Book1氢惋,類型為 Book
struct Books Book1;
// 單個賦值
// Book1.title = "C Programming";
strcpy( Book1.title, "C Programming");
Book1.subject = "iOS 10"; /* 這個是指針, 可以直接賦值 */
// 指定初始化洞翩,成員順序可以不定
struct Books book = {
.title = "ios開發(fā)",
.subject= "計算機",
.book_id = 100
};
// 按照成員聲明的順序初始化
struct Books book1 = {"iOS", "計算機", 100};
說明: title是數(shù)組, 不是指針, 指針賦值可以使用點的方式或者->, 數(shù)組賦值字符串只能使用strcpy()的方式
你也可以在定義結(jié)構(gòu)體的同時定義結(jié)構(gòu)體變量:
這種寫法是在定義時聲明了變量為subject, 使用時不需要struct Subject subject 這種寫法
而是直接使用subject就可以了
struct Subject {
char *sub;
int book_id;
} subject;
使用
subject.sub = "計算機"; //不需要使用struct關(guān)鍵字聲明
其他一些定義結(jié)構(gòu)體的方式
- 在定義結(jié)構(gòu)體的同時定義多個結(jié)構(gòu)體變量:
struct Subject {
char *sub;
int book_id;
} subject1, subject2;
- 在定義結(jié)構(gòu)體的同時定義結(jié)構(gòu)體變量并賦值
struct Subject {
char *sub;
int book_id;
} subject = {"計算機", 100};
3.如果需要變量是固定的,后面不需要再使用結(jié)構(gòu)體名定義其他變量焰望,那么在定義時也可以不給出結(jié)構(gòu)體名骚亿,如下所示:
struct {
char *sub;
int book_id;
} subject = {"計算機", 100};
結(jié)構(gòu)體設(shè)置別名
/**
* 這種寫法是給
* struct person {
char *name;
}
* 設(shè)置一個別名Person
*/
typedef struct person {
char *name;
} Person;
在使用時 Person <==> struct person , 二者是等價的
需要注意的是,結(jié)構(gòu)體是一種自定義的數(shù)據(jù)類型熊赖,是創(chuàng)建變量的模板来屠,不占用內(nèi)存空間;結(jié)構(gòu)體變量才包含了實實在在的數(shù)據(jù)震鹉,需要內(nèi)存空間來存儲俱笛。
結(jié)構(gòu)體數(shù)組
所謂結(jié)構(gòu)體數(shù)組,是指數(shù)組中的每個元素都是一個結(jié)構(gòu)體传趾。在實際應(yīng)用中迎膜,結(jié)構(gòu)體數(shù)組常被用來表示一個擁有相同數(shù)據(jù)結(jié)構(gòu)的群體,比如一個班的學(xué)生墨缘、一個車間的職工等。
struct stu {
char *name; //姓名
int num; //學(xué)號
int age; //年齡
char group; //所在小組
float score; //成績
} class[5];
結(jié)構(gòu)體數(shù)組在定義的同時也可以初始化零抬,例如:
struct stu {
char *name; //姓名
int num; //學(xué)號
int age; //年齡
char group; //所在小組
float score; //成績
} class[5] = {
{"Li ping", 5, 18, 'C', 145.0},
{"Zhang ping", 4, 19, 'A', 130.5},
{"He fang", 1, 18, 'A', 148.5},
{"Cheng ling", 2, 17, 'F', 139.0},
{"Wang ming", 3, 17, 'B', 144.5}
};
操作
// 取值
class[4].score;
// 修改 Li ping 的學(xué)習(xí)小組;
class[0].group = 'B';
結(jié)構(gòu)體和指針
指針也可以指向一個結(jié)構(gòu)體镊讼,定義的形式一般為:
struct 結(jié)構(gòu)體名 *變量名;
// 聲明結(jié)構(gòu)體變量
struct Books book = {"iOS", "計算機", 100};
/* 結(jié)構(gòu)體指針 */
struct Books *strP = &book;
/* 獲取結(jié)構(gòu)體成員 */
printf("%s", strP->title);
printf("%s", (*strP).title);
注意,結(jié)構(gòu)體變量名和數(shù)組名不同平夜,數(shù)組名在表達式中會被轉(zhuǎn)換為數(shù)組指針蝶棋,而結(jié)構(gòu)體變量名不會,無論在任何表達式中它表示的都是整個集合本身忽妒,要想取得結(jié)構(gòu)體變量的地址玩裙,必須在前面加&兼贸,所以給 pstu 賦值只能寫作:
struct stu *pstu = &stu1;
而不能寫作:
struct stu *pstu = stu1;
還應(yīng)該注意,結(jié)構(gòu)體和結(jié)構(gòu)體變量是兩個不同的概念:結(jié)構(gòu)體是一種數(shù)據(jù)類型吃溅,是一種創(chuàng)建變量的模板溶诞,編譯器不會為它分配內(nèi)存空間,就像 int决侈、float螺垢、char 這些關(guān)鍵字本身不占用內(nèi)存一樣;結(jié)構(gòu)體變量才包含實實在在的數(shù)據(jù)赖歌,才需要內(nèi)存來存儲枉圃。下面的寫法是錯誤的,不可能去取一個結(jié)構(gòu)體名的地址庐冯,也不能將它賦值給其他變量:
struct stu *pstu = &stu;
struct stu *pstu = stu;
獲取結(jié)構(gòu)體成員
通過結(jié)構(gòu)體指針可以獲取結(jié)構(gòu)體成員孽亲,一般形式為:
(*pointer).memberName
或者:
pointer->memberName
第一種寫法中,.的優(yōu)先級高于展父,(pointer)兩邊的括號不能少返劲。如果去掉括號寫作pointer.memberName,那么就等效于(pointer.numberName)犯祠,這樣意義就完全不對了旭等。
第二種寫法中,->是一個新的運算符衡载,習(xí)慣稱它為“箭頭”搔耕,有了它,可以通過結(jié)構(gòu)體指針直接取得結(jié)構(gòu)體成員痰娱;這也是->在C語言中的唯一用途弃榨。