所謂結(jié)構(gòu)體指針就是指向結(jié)構(gòu)體變量的指針,一個(gè)結(jié)構(gòu)體變量的起始地址就是這個(gè)結(jié)構(gòu)體變量的指針。如果把一個(gè)結(jié)構(gòu)體變量的起始地址存放在一個(gè)指針變量中,那么,這個(gè)指針變量就指向該結(jié)構(gòu)體變量。
目錄
一、指向結(jié)構(gòu)體變量的指針
1.1舉例說明
二、指向結(jié)構(gòu)體數(shù)組的指針
2.1舉例說明
2.2注意
三、用結(jié)構(gòu)體變量和結(jié)構(gòu)體變量的指針作函數(shù)參數(shù)
3.1引入
3.2舉例說明
一、指向結(jié)構(gòu)體變量的指針
1.1舉例說明
指向結(jié)構(gòu)體對(duì)象的指針變量既可指向結(jié)構(gòu)體變量,也可指向結(jié)構(gòu)體數(shù)組中的元素。指針變量的基類型必須與結(jié)構(gòu)體變量的類型相同。例如:
struct Student* pt;????????//pt可以指向struct Student類型的變量或數(shù)組元素
先通過一個(gè)例子了解什么是指向結(jié)構(gòu)體變量的指針變量以及怎樣使用它。
舉例:通過指向結(jié)構(gòu)體變量的指針變量輸出結(jié)構(gòu)體變量中成員的信息。
解題思路:在已有的基礎(chǔ)上,本題要解決兩個(gè)問題:(1)怎樣對(duì)結(jié)構(gòu)體變量成員賦值;(2)怎樣通過指向結(jié)構(gòu)體變量的指針訪問結(jié)構(gòu)體變量中成員。
#include <stdio.h>
#include <string.h>
int main()
{
struct Student //聲明結(jié)構(gòu)體類型struct Student
{
long num;
char name[20]; char sex;
float score;
};
struct Student stu_1; //定義struct Student類型的變量stu_1
struct Student* p; //定義指向struct Student 類型數(shù)據(jù)的指針變量p
p = &stu_1; //p指向stu_1
stu_1.num = 1001; //對(duì)結(jié)構(gòu)體變量的成員賦值
strcpy_s(stu_1.name, "Li Ming");//用字符串復(fù)制函數(shù)給stu_1.name賦值
stu_1.sex = 'M';
stu_1.score = 95;
printf("No.:%ld\nname :%s\nsex :%c\nscore :%5.1f\n", stu_1.num, stu_1.name, stu_1.sex, stu_1.score);
printf("\nNo.:%ld\nname :%s\nsex :%c\nscore :%5.1f\n", (*p).num, (*p).name, (*p).sex, (*p).score);
return 0;
}
運(yùn)行結(jié)果:
程序分析:
兩個(gè) printf 函數(shù)輸出的結(jié)果是相同的。在主函數(shù)中聲明了 struct Student 類型,然后定義一個(gè) struct Student 類型的變量 stu_1。又定義一個(gè)指針變量 p,它指向一個(gè) struct Student 類型的對(duì)象。將結(jié)構(gòu)體變量 stu_1 的起始地址賦給指針變量 p,也就是使 p 指向 stu_1。然后對(duì) stu_1 的各成員賦值。
第 1 個(gè) printf 函數(shù)是通過結(jié)構(gòu)體變量名 stu_1 訪問它的成員,輸出 stu_1 的各個(gè)成員的值。stu_1.num 表示 stu_1 中的成員 num,依此類推。第 2 個(gè) printf 函數(shù)是通過指向結(jié)構(gòu)體變量的指針變量訪問它的成員,輸出 stu_1 各成員的值,使用的是 (*p).num 這樣的形式。(*p) 表示 p 指向的結(jié)構(gòu)體變量,(*p).num 是 p 所指向的結(jié)構(gòu)體變量中的成員 num。注意 *p 兩側(cè)的括號(hào)不可省,因?yàn)槌蓡T運(yùn)算符 “.” 優(yōu)先于 “ * ” 運(yùn)算符,*p.num 就等價(jià)于 *(p.num) 了。
說明:
為了使用方便和直觀,C 語言允許把 (*p).num 用 p->num 代替,“->”代表一個(gè)箭頭,p->num 表示 p 所指向的結(jié)構(gòu)體變量中的 num 成員。同樣,(*p).name 等價(jià)于 p->name。“->” 稱為指向運(yùn)算符。
如果 p 指向一個(gè)結(jié)構(gòu)體變量 stu,以下 3 種用法等價(jià):
①stu.成員名????????(如stu.num);
②(*p).成員名???????(如(*p).num);③p->成員名????????(如p->num)。
二、指向結(jié)構(gòu)體數(shù)組的指針
2.1舉例說明
可以用指針變量指向結(jié)構(gòu)體數(shù)組的元素。請(qǐng)分析下面的例子。
舉例:有 3 個(gè)學(xué)生的信息,放在結(jié)構(gòu)體數(shù)組中,要求輸出全部學(xué)生的信息。
解題思路:用指向結(jié)構(gòu)體變量的指針來處理:
(1)聲明結(jié)構(gòu)體類型 struct Student,并定義結(jié)構(gòu)體數(shù)組,同時(shí)使之初始化;
(2)定義一個(gè)指向 struct Student 類型數(shù)據(jù)的指針變量p;
(3)使p指向結(jié)構(gòu)體數(shù)組的首元素,輸出它指向的元素中的有關(guān)信息;
(4)使p指向結(jié)構(gòu)體數(shù)組的下一個(gè)元素,輸出它指向的元素中的有關(guān)信息;
(5)再使p指向結(jié)構(gòu)體數(shù)組的下一個(gè)元素,輸出它指向的元素中的有關(guān)信息。
#include<stdio.h>
struct Student //聲明結(jié)構(gòu)體類型struct Student
{
int num;
char name[20];
char sex;
int age;
};
struct Student stu[3] = { {1001,"Li Ming" , 'M',18},{1002,"Zhang San" ,'M',19},{1003,"Wang Wu",'F',20} }; //定義結(jié)構(gòu)體數(shù)組并初始化
int main()
{
struct Student* p; //定義指向struct Student結(jié)構(gòu)體變量的指針變量
printf(" No.Name sex age\n");
for (p = stu; p < stu + 3; p++)
printf("%5d %-20s %2c %4d\n", p->num, p->name, p->sex, p->age);//輸出結(jié)果
return 0;
}
運(yùn)行結(jié)果:
程序分析:
p 是指向 struct Student 結(jié)構(gòu)體類型數(shù)據(jù)的指針變量。在 for 語句中先使 p 的初值為 stu,也就是數(shù)組 stu 中序號(hào)為 0 的元素(即 stu[0] )的起始地址。在第 1 次循環(huán)中輸出 stu[0] 的各個(gè)成員值。然后執(zhí)行 p++,使 p 自加 1。p 加 1 意味著 p 所增加的值為結(jié)構(gòu)體數(shù)組 stu 的一個(gè)元素所占的字節(jié)數(shù)(在 Visual C++ 環(huán)境下,本例中一個(gè)元素所占的字節(jié)數(shù)理論上為 4+20+1+4 = 29 字節(jié),實(shí)際分配 32 字節(jié))。執(zhí)行 p++ 后 p 的值等于 stu+1,p 指向stu[1]。在第 2 次循環(huán)中輸出 stu[1] 的各成員值。在執(zhí)行 p++ 后,p 的值等于 stu+2,再輸出 stu[2] 的各成員值。在執(zhí)行 p++ 后,p 的值變?yōu)?stu+3,已不再小于 stu+3 了,不再執(zhí)行循環(huán)。
2.2注意
(1)如果 p 的初值為 stu,即指向 stu 的序號(hào)為 0 的元素,p 加 1 后,p 就指向下一個(gè)元素。
例如:
(++p)->num????????先使p自加1,然后得到 p 指向的元素中的 num 成員值(即1002)
(p++)->num????????先求得 p->num的值(即1001),然后再使 p 自加 1,指向 stu[1] 請(qǐng)注意以上二者的不同。
(2)程序定義了 p 是一個(gè)指向 struct Student 類型對(duì)象的指針變量,它用來指向一個(gè) struct Student 類型的對(duì)象,不應(yīng)用來指向 stu 數(shù)組元素中的某一成員。
例如,下面的用法是不對(duì)的:
p = stu[1].name; // stu[1].name是stu[1]元素中的成員name的首字符的地址
編譯時(shí)將給出 “ 警告 ” 信息,表示地址的類型不匹配。不要認(rèn)為反正 p 是存放地址的,可以將任何地址賦給它。如果一定要將某一成員的地址賦給 p,可以用強(qiáng)制類型轉(zhuǎn)換,先將成員的地址轉(zhuǎn)換成 p 的類型。例如:
p = (struct Student*)stu[0].name;
此時(shí),p 的值是 stu[0] 元素的 name 成員的起始地址??梢杂?“ printf ("%s", p); ” 輸出 stu[0] 中成員 name 的值。但是,p 仍保持原來的類型。如果執(zhí)行 “ printf( "%s",p+1); ”,則會(huì)輸出 stu[1] 中 name 的值。執(zhí)行 p++ 時(shí),p 的值的增量是結(jié)構(gòu)體 struct Student 的長(zhǎng)度。
三、用結(jié)構(gòu)體變量和結(jié)構(gòu)體變量的指針作函數(shù)參數(shù)
3.1引入
將一個(gè)結(jié)構(gòu)體變量的值傳遞給另一個(gè)函數(shù),有 3個(gè)方法:
(1)用結(jié)構(gòu)體變量的成員作參數(shù)。例如,用 stu[1].num 或 stu[2].name 作函數(shù)實(shí)參,將實(shí)參值傳給形參。用法和用普通變量作實(shí)參是一樣的,屬于“值傳遞”方式。應(yīng)當(dāng)注意實(shí)參與形參的類型保持一致。
(2)用結(jié)構(gòu)體變量作實(shí)參。用結(jié)構(gòu)體變量作實(shí)參時(shí),采取的也是 “ 值傳遞 ” 的方式,將結(jié)構(gòu)體變量所占的內(nèi)存單元的內(nèi)容全部按順序傳遞給形參,形參也必須是同類型的結(jié)構(gòu)體變量。在函數(shù)調(diào)用期間形參也要占用內(nèi)存單元。這種傳遞方式在空間和時(shí)間上開銷較大,如果結(jié)構(gòu)體的規(guī)模很大時(shí),開銷是很可觀的。此外,由于采用值傳遞方式,如果在執(zhí)行被調(diào)用函數(shù)期間改變了形參(也是結(jié)構(gòu)體變量)的值,該值不能返回主調(diào)函數(shù),這往往造成使用上的不便。因此一般較少用這種方法。
(3)用指向結(jié)構(gòu)體變量(或數(shù)組元素)的指針作實(shí)參,將結(jié)構(gòu)體變量(或數(shù)組元素)的地址傳給形參。
3.2舉例說明
舉例:有 n 個(gè)結(jié)構(gòu)體變量,內(nèi)含學(xué)生學(xué)號(hào),姓名和 3 門課程的成績(jī)。要求輸出平均成績(jī)最高的學(xué)生的信息(包括學(xué)號(hào)、姓名、3 門課程成績(jī)和平均成績(jī))。
解題思路:將 n 個(gè)學(xué)生的數(shù)據(jù)表示為結(jié)構(gòu)體數(shù)組(有 n 個(gè)元素)。按照功能函數(shù)化的思想,分別用 3 個(gè)函數(shù)來實(shí)現(xiàn)不同的功能:(1)用input函數(shù)來輸入數(shù)據(jù)和求各學(xué)生平均成績(jī)。(2)用max函數(shù)來找平均成績(jī)最高的學(xué)生。(3)用print函數(shù)來輸出成績(jī)最高學(xué)生的信息。在主函數(shù)中先后調(diào)用這3個(gè)函數(shù),用指向結(jié)構(gòu)體變量的指針作實(shí)參。最后得到結(jié)果。
#include<stdio.h>
#define N 3 //學(xué)生數(shù)為3
struct Student //定義結(jié)構(gòu)體類型
{
int num;
char name[20];
float score[3];
float aver;
};
int main()
{
void input(struct Student stu[]); //函數(shù)聲明
struct Student max(struct Student stu[]); //函數(shù)聲明
void print(struct Student stu); //函數(shù)聲明
struct Student stu[N]; //定義結(jié)構(gòu)體數(shù)組
struct Student* p = stu; //定義結(jié)構(gòu)體指針
input(stu); //調(diào)用input函數(shù)
print(max(stu)); //調(diào)用print函數(shù),以max函數(shù)的返回值作為實(shí)參
return 0;
}
void input(struct Student stu[]) //input函數(shù)
{
printf("請(qǐng)輸入各學(xué)生的信息:學(xué)號(hào),姓名,3門課成績(jī)\n");
for (int i = 0; i < N; i++)
{
scanf_s("%d %s %f %f %f", &stu[i].num, stu[i].name, 20, &stu[i].score[0], &stu[i].score[1], &stu[i].score[2]);
stu[i].aver = (stu[i].score[0] + stu[i].score[1] + stu[i].score[2]) / 3.0;
}
}
struct Student max(struct Student stu[]) //max函數(shù)
{
int k = 0;
for (int i = 1; i < N; i++) //找出平均值最大的學(xué)生
{
if (stu[i].aver > stu[k].aver)
k = i;
}
return stu[k];
}
void print(struct Student stu) //print函數(shù)
{
printf("\n成績(jī)最高的學(xué)生是:\n");
printf("學(xué)號(hào):%d\n姓名:%s\n三門課成績(jī):%5.1f,%5.1f,%5.1f\n平均成績(jī):%6.2f\n",
stu.num, stu.name, stu.score[0], stu.score[1], stu.score[2], stu.aver);
}
運(yùn)行結(jié)果:
程序分析:
(1)結(jié)構(gòu)體類型 struct Student 中包括 num(學(xué)號(hào)),name(姓名),數(shù)組score( 3 門課成績(jī))和 aver (平均成績(jī))。在輸入數(shù)據(jù)時(shí)只輸入學(xué)號(hào),姓名和 3 門課成績(jī),未給 aver 賦值。aver 的值是在 input 函數(shù)中計(jì)算出來的。
(2)在主函數(shù)中定義了結(jié)構(gòu)體 struct Student 類型的數(shù)組 stu 和指向 struct Student 類型數(shù)據(jù)的指針變量 p,使 p 指向 stu 數(shù)組的首元素 stu[0]。在調(diào)用 input 函數(shù)時(shí),用指針變量 p 作為函數(shù)實(shí)參, input 函數(shù)的形參是 struct Student 類型的數(shù)組 stu (注意形參數(shù)組 stu 和主函數(shù)中的數(shù)組 stu 都是局部數(shù)據(jù),雖然同名,但在調(diào)用函數(shù)進(jìn)行虛實(shí)結(jié)合前二者代表不同的對(duì)象,互相間沒有關(guān)系)。在調(diào)用 input 函數(shù)時(shí),將主函數(shù)中的 stu 數(shù)組的首元素的起始地址傳給形參數(shù)組 stu,使形參數(shù)組 stu 與主函數(shù)中的 stu 數(shù)組具有相同的地址。因此在 input 函數(shù)中向形參數(shù)組 stu 輸入數(shù)據(jù)就等于向主函數(shù)中的 stu 數(shù)組輸入數(shù)據(jù)。
在用 scanf_s 函數(shù)輸入數(shù)據(jù)后,立即計(jì)算出該學(xué)生的平均成績(jī),stu[i].ave r代表序號(hào)為 i 的學(xué)生的平均成績(jī)。input 函數(shù)無返回值,它的作用是給 stu 數(shù)組各元素賦予確定的值。
(3)在主函數(shù)中調(diào)用 print 函數(shù),實(shí)參是 max(p)。其調(diào)用過程是先調(diào)用 max 函數(shù)(以 p 為實(shí)參),得到 max(p) 的值(此值是一個(gè) strct Student 類型的數(shù)據(jù))。然后用它調(diào)用print函數(shù)。
現(xiàn)在先分析調(diào)用 max 函數(shù)的過程:與前相同,指針變量 p 將主函數(shù)中的 stu 數(shù)組的首元素的起始地址傳給形參數(shù)組 stu,使形參數(shù)組 stu 與主函數(shù)中的 stu 數(shù)組具有相同的地址。在 max 函數(shù)中對(duì)形參數(shù)組的操作就是對(duì)主函數(shù)中的 stu 數(shù)組的操作。在 max 函數(shù)中,將各人平均成績(jī)與當(dāng)前的 “最高平均成績(jī)” 比較,將平均成績(jī)最高的學(xué)生在數(shù)組 stu 中的序號(hào)存放在變量 m 中,通過 return 語句將 stu[m] 的值返回主函數(shù)。請(qǐng)注意:stu[m] 是一個(gè)結(jié)構(gòu)體數(shù)組的元素。max 函數(shù)的類型為 struct Student 類型。
(4)用 max(p) 的值(是結(jié)構(gòu)體數(shù)組的元素)作為實(shí)參調(diào)用 print 函數(shù)。print 函數(shù)的形參 stu 是? struct Student 類型的變量(而不是 struct Student 類型的數(shù)組)。在調(diào)用時(shí)進(jìn)行虛實(shí)結(jié)合,把 stu[m] 的值(是結(jié)構(gòu)體元素)傳遞給形參 stu ,這時(shí)傳遞的不是地址,而是結(jié)構(gòu)體變量中的信息。在 print 函數(shù)中輸出結(jié)構(gòu)體變量中各成員的值。
(5)以上 3 個(gè)函數(shù)的調(diào)用,情況各不相同:
①調(diào)用 input 函數(shù)時(shí),實(shí)參是指針變量 p,形參是結(jié)構(gòu)體數(shù)組,傳遞的是結(jié)構(gòu)體元素的起始地址,函數(shù)無返回值。
②調(diào)用 max 函數(shù)時(shí),實(shí)參是指針變量 p,形參是結(jié)構(gòu)體數(shù)組,傳遞的是結(jié)構(gòu)體元素的起始地址,函數(shù)的返回值是結(jié)構(gòu)體類型數(shù)據(jù)。文章來源:http://www.zghlxwxcb.cn/news/detail-735248.html
③調(diào)用 print 函數(shù)時(shí),實(shí)參是結(jié)構(gòu)體變量(結(jié)構(gòu)體數(shù)組元素),形參是結(jié)構(gòu)體變量,傳遞的是結(jié)構(gòu)體變量中各成員的值,函數(shù)無返回值。文章來源地址http://www.zghlxwxcb.cn/news/detail-735248.html
到了這里,關(guān)于C語言自定義數(shù)據(jù)類型(三)結(jié)構(gòu)體指針的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!