37.結構體指標(指向結構體的指標)
當一個指標變數指向結構體時,我們就稱它為結構體指標。C語言結構體指標的定義形式一般為:
struct 結構體名 *變數名;下面是一個定義結構體指標的例項:
//結構體
struct stu{
char *name; //姓名
int num; //學號
int age; //年齡
char group; //所在小組
float score; //成績
} stu1 = { "Tom", 12, 18, 'A', 136.5 };
//結構體指標
struct stu *pstu = &stu1;
也可以在定義結構體的同時定義結構體指標:
struct stu{ char *name; //姓名 int num; //學號 int age; //年齡 char group; //所在小組 float score; //成績 } stu1 = { "Tom", 12, 18, 'A', 136.5 }, *pstu = &stu1;
注意,結構體變數名和陣列名不同,陣列名在表示式中會被轉換為陣列指標,而結構體變數名不會,無論在任何表示式中它表示的都是整個集合本身,要想取得結構體變數的地址,必須在前面加&
,所以給 pstu 賦值只能寫作:
struct stu *pstu = &stu1;
而不能寫作:
struct stu *pstu = stu1;
還應該注意,結構體和結構體變數是兩個不同的概念:結構體是一種資料型別,是一種建立變數的模板,編譯器不會為它分配記憶體空間,就像 int、float、char 這些關鍵字本身不佔用記憶體一樣;結構體變數才包含實實在在的資料,才需要記憶體來儲存。下面的寫法是錯誤的,不可能去取一個結構體名的地址,也不能將它賦值給其他變數:
struct stu *pstu = &stu;
struct stu *pstu = stu;
一、獲取結構體成員
通過結構體指標可以獲取結構體成員,一般形式為:
(*pointer).memberName或者:
pointer->memberName第一種寫法中,.
的優先順序高於*
,(*pointer)
兩邊的括號不能少。如果去掉括號寫作*pointer.memberName
,那麼就等效於*(pointer.memberName)
,這樣意義就完全不對了。
第二種寫法中,->
是一個新的運算子,習慣稱它為“箭頭”,有了它,可以通過結構體指標直接取得結構體成員;這也是->
上面的兩種寫法是等效的,我們通常採用後面的寫法,這樣更加直觀。
【示例】結構體指標的使用。
#include <stdio.h>
int main(){
struct{
char *name; //姓名
int num; //學號
int age; //年齡
char group; //所在小組
float score; //成績
} stu1 = { "Tom", 12, 18, 'A', 136.5 }, *pstu = &stu1;
//讀取結構體成員的值
printf("%s的學號是%d,年齡是%d,在%c組,今年的成績是%.1f!\n", (*pstu).name, (*pstu).num, (*pstu).age, (*pstu).group, (*pstu).score);
printf("%s的學號是%d,年齡是%d,在%c組,今年的成績是%.1f!\n", pstu->name, pstu->num, pstu->age, pstu->group, pstu->score);
return 0;
}
執行結果:
Tom的學號是12,年齡是18,在A組,今年的成績是136.5!
Tom的學號是12,年齡是18,在A組,今年的成績是136.5!
【示例】結構體陣列指標的使用。
#include <stdio.h>
struct stu{
char *name; //姓名
int num; //學號
int age; //年齡
char group; //所在小組
float score; //成績
}stus[] = {
{"Zhou ping", 5, 18, 'C', 145.0},
{"Zhang ping", 4, 19, 'A', 130.5},
{"Liu fang", 1, 18, 'A', 148.5},
{"Cheng ling", 2, 17, 'F', 139.0},
{"Wang ming", 3, 17, 'B', 144.5}
}, *ps;
int main(){
//求陣列長度
int len = sizeof(stus) / sizeof(struct stu);
printf("Name\t\tNum\tAge\tGroup\tScore\t\n");
for(ps=stus; ps<stus+len; ps++){
printf("%s\t%d\t%d\t%c\t%.1f\n", ps->name, ps->num, ps->age, ps->group, ps->score);
}
return 0;
}
執行結果:
Name Num Age Group Score
Zhou ping 5 18 C 145.0
Zhang ping 4 19 A 130.5
Liu fang 1 18 A 148.5
Cheng ling 2 17 F 139.0
Wang ming 3 17 B 144.5
二、結構體指標作為函式引數
結構體變數名代表的是整個集合本身,作為函式引數時傳遞的整個集合,也就是所有成員,而不是像陣列一樣被編譯器轉換成一個指標。如果結構體成員較多,尤其是成員為陣列時,傳送的時間和空間開銷會很大,影響程式的執行效率。所以最好的辦法就是使用結構體指標,這時由實參傳向形參的只是一個地址,非常快速。
【示例】計算全班學生的總成績、平均成績和以及 140 分以下的人數。
#include <stdio.h>
struct stu{
char *name; //姓名
int num; //學號
int age; //年齡
char group; //所在小組
float score; //成績
}stus[] = {
{"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}
};
void average(struct stu *ps, int len);
int main(){
int len = sizeof(stus) / sizeof(struct stu);
average(stus, len);
return 0;
}
void average(struct stu *ps, int len){
int i, num_140 = 0;
float average, sum = 0;
for(i=0; i<len; i++){
sum += (ps + i) -> score;
if((ps + i)->score < 140) num_140++;
}
printf("sum=%.2f\naverage=%.2f\nnum_140=%d\n", sum, sum/5, num_140);
}
執行結果:
sum=707.50
average=141.50
num_140=2