指標講解及注意事項(Plus)

2020-10-01 08:00:12

什麼是指標

指標是C語言的核心概念,也是C語言的特色和精華所在,更是初學者學習的難點所在。掌握了指標,才談得上是真正掌握了C語言,指標也就是記憶體地址,指標變數是用來存放記憶體地址的變數,不同型別的指標變數所佔用的儲存單元長度是相同的,而存放資料的變數因資料的型別不同,所佔用的儲存空間長度也不同。有了指標以後,不僅可以對資料本身,也可以對儲存資料的變數地址進行操作。

指標的作用

1、指標就是指向一個特定記憶體地址的一個變數。指標可以有效地表示覆雜的資料結構、動態分配記憶體、高效地使用陣列和字串、使得呼叫函數時得到多個返回值等。指標的應用往往與陣列聯絡在一起,是最頻繁的,也是最基礎的。在定義陣列和函數時,系統都會為其自動分配一個指向其首地址的指標。對於一個陣列,其名稱就是一個指標變數。

2、指標只是一個變數,它儲存一個記憶體地址。如果傳入一個地址,比傳入一個副本效率要高,因為少了一個拷貝過程。

3、指標能夠有效的表示資料結構,能動態分配記憶體,能較方便的使用字串,有效的使用陣列。

4、指標直接與資料等的儲存地址有關,是比較重要的。比如,地址傳遞比值傳遞高效,因為值傳遞先從實參的地址中提出值,再賦值給形參帶入函數計算;而指標則把形參的地址直接指向實參地址,使用時直接提出資料,使效率提高,特別在頻繁賦值等情況下,缺點是在函數中也可以改變其值。

指標的優點

1.可以提高程式的編譯效率和執行速度減小系統開銷,使程式更加簡潔。

2.通過指標被呼叫函數可以向呼叫函數處返回除正常的返回值之外的其他資料,從而實現兩者間的雙向通訊。

3.利用指標可以實現動態記憶體分配(例如:動態陣列)。

4.指標還用於表示和實現各種複雜的資料結構(例如:連結串列,樹),從而為編寫出更加高品質的程式奠定基礎。

5.利用指標可以直接操縱記憶體地址,從而可以完成和組合語言類似的工作。

6.讓程式程式碼更加便利接觸硬體控制等…

指標的缺點

指標可以操作任意記憶體,所以指標很靈活、很強大,但也引入了複雜性,並且申請記憶體之後需要手動釋放如果不釋放則會造成記憶體漏失(可以使用智慧指標來防止記憶體漏失後面講)。

指標的型別

我們都知道,變數有不同的型別,整型,浮點型,字元型等等。那指標有沒有型別呢?其實是有的!比如

int *p;   //定義一個int 型指標變數變數名為p

舉例:

int* p;      //可以指向一個int型變數或者一個int型陣列
float* p;    //可以指向一個float型變數或者一個float型陣列
double* p;   //可以指向一個double型變數或者一個double陣列
char* p;     //可以指向一個char型變數或者一個char陣列
void* p;     //可以指向任意變數使用時需要強制轉換為該指標所指變數的型別
	

範例:

#include<stdio.h>
int main(void)
{
	int* int_p;         //可以指向一個int型變數或者一個int型陣列
	int A = 10;
	int AA[10] = { 1,2,3,4,5,6,7,8,9,10 };
	int_p = &A;         //將int_p指向A的地址

	printf("A的值為:%d     A的地址為:%p   指標int_p指向A後     int_p所儲存的地址為:%p    *p的內容為:%d    ", A, &A, int_p, *int_p);

	//當指標指向一個變數時可以通過 *int_p=666時,int_p所指向的那個變數的值也會等於666
	*int_p = 666;
	printf("*int_p=666 後 A的內容為:%d\n\n", A);

	//注意:AA和AA[0]意思一樣!!
	int_p = AA;         //將int_p指向AA的首地址,相當於int_p=AA[0];      

	//注意:AA和AA[0]意思一樣!!!
	printf("陣列AA的值為:%d     陣列AA的地址為:%p   指標int_p指向AA後     int_p所儲存的地址為:%p    *int_p的內容為:%d\n\n", AA[0], &AA, int_p, *int_p);


	//重點:當p指向一個變數時   輸出p表示 輸出p所指向的 變數的地址(記住是:"變數的地址" ), 輸出*p表示 輸出p所指向的 變數的內容(記住是:"變數的內容" );
	
	printf("現在int_p已經指向了陣列AA, 現在用*int_p的方式輸出陣列AA的內容  \n\n");
	printf("輸出為:  ");
	for (int i = 0; i < 10; i++, int_p++)    //i是用來計數,    int_p++的意思為:每執行一次int_p就往後移動一個單位(這裡單位的意思是:當指標為int型時單位就為4,當指標為double型時,一個單位就為8  );
	{
		printf("%d  ", *int_p);
	}

	//char指標與int 型指標類似,double和float和上面的例子中的int型指標用法幾乎一模一樣,下面講解char和void型指標

	char ch = 'A';
	char* char_p;
	char_p = &ch;
	printf("\n\nch的值為:%c     ch的地址為:%p   指標char_p指向ch後     char_p所儲存的地址為:%p    *char_p的內容為:%c\n\n", ch, &ch, char_p, *char_p);

	//char型指標也可以指向一個字元組

	char_p = (char *)"AAAA";   //有些編譯器不需要強制型別轉換,可以直接char_p="AAAA";


	//注意char型指標指向一個字串輸出時不需要像其他型別(例如:int float)一樣在指標前加 * (如果char 型指標指向一個字元陣列用*char_p進行輸出 這是錯的)
	printf("指標char_p指向一個字串\"AAAA\"後     char_p所儲存的地址為:%p    char_p的內容為:%s\n\n", char_p, char_p);   


	//void型指標賦值或輸出指標所指的變數內容是都需要進行強制型別轉換
	void* void_p;
	void_p =(char *) "AAAAA";
	printf("將\"AAAAA\"進行強制型別轉換賦給void_p  例:void_p =(char *) \"AAAAA\";     (char *)void_p的輸出結果為:%s\n\n", (char *)void_p);
	int Num = 666;

	void_p =(int *) &Num;

	printf("將int型變數Num進行強制型別轉換賦給void_p  例:void_p =(int *) &Num;     *((int *)void_p)的輸出結果為:%d      ", *((int *)void_p));
}

執行結果:
結果

陣列和指標的區別與聯絡

這位大佬寫的很好也很詳細,這部分就看他的吧

指標與陣列

指標與陣列的關係 我們可以從下面這個方面入手。在C語言建立之初,很大一部分C語言的使用者是編譯器的設計者,所以為了迎合這些人的口味兒,C語言做了很多特定的規則,這些規則後來在標準化的過程中被委員會採納,成了語言標準的一部分。具體到指標與陣列這一塊兒,我們同樣從兩個方面來看,一是作為一個語言,陣列是必須要支援的一種陣列型別,原因很簡單,陣列是線性表的直接體現。而從編譯器設計者的角度來看,如果為陣列專門設計一套實現標準會非常繁雜(事實上,後來C++完成了這一任務,它就是標準庫中的vector容器)。這一對矛盾最後以雙方的相互妥協得以解決,而解決方法就是利用現有的指標來間接實現陣列。然而,陣列與指標終究不是一個東西,所以,語言在設計過程中就必須在二者之間和稀泥。到最後,就形成了這樣一對令人頭大的冤家。瞭解了這一背景,你就不會為他倆撲朔迷離的關係而感到驚訝了。

對於編譯器而言,一個陣列是一個地址,一個指標是一個地址的地址。

陣列要麼在靜態儲存區被建立(如全域性陣列),要麼在棧上被建立。陣列名對應著(而不是指向)一塊記憶體,其地址與容量在生命期內保持不變,只有陣列的內容可以改變。

//可以被更改的值叫左值,不可以被更改值的叫右值

void main(void)
{ 
	int a[10];
	a ++;//錯誤,a是左值,不能更改
}

指標可以隨時指向任意型別的記憶體塊, 遠比陣列靈活,但也更危險。下表是指標和陣列一個簡單的比較

陣列和指標的優勢

陣列的優勢

1.儲存資料

2.直接存取資料

3.用於儲存數目固定且型別相同的資料

4.編譯器自動分配和刪除

5.自身即為資料名

指標的優勢

1.儲存地址

2.間接存取資料,先取得指標的內容,然後以它為地址,取得資料

3.通常用於動態資料結構(如連結串列)

4.動態的分配和刪除,相關函數為malloc()和free() C++中new和delete

5.通常指向隱式資料(如通過malloc或new動態分配的記憶體)

指標和陣列都可以在初始化的時候賦予字串常數。儘管看上去一樣,底層機制卻不同。指標在定義的時候,編譯器並不會為指標所指向的物件分配記憶體空間,它只是分配指標變數的空間(32位元的系統給指標分配的記憶體為4位元組,64位元的系統給指標分配的記憶體為8位元組)。除非以一個字串常數對其進行初始化。下面的定義建立了一個字串常數(為其分配了記憶體空間)

char* char_p = "abcde";

在ANSI C中,初始化指標時所指向的字串被定義為唯讀,如果想通過指標修改字串的
時候,會產生未定義的行為(通常編譯時就會報錯)。

char型陣列也可以用字串常數進行初始化,但是其內容可以被修改。

內容的複製和比較

不能對陣列進行位元組複製和比較,對於兩個char型陣列a, b, 不能用b = a進行復制,而應當使用標準庫函數strcpy()。也不能使用if(b == a)進行比較,應當使用strcmp()。

而對於指標p,如果要想將陣列a中的內容複製,要先申請一塊記憶體區域(malloc(strlen(a))+1),然後使用strcpy()進行拷貝。

指標與陣列的區別: C語言把記憶體劃分成四個區,它把一般的變數和陣列等存在於記憶體中的棧區,所以陣列在C語言的定義中只是一組同型別的普通變數,即使這個變數有可能是指標。所以他的作用比指標小的很多,而指標可以指向任何區的任何資料,所以就會覺得指標和陣列名很像,但是必須要注意的是,陣列名只是指標中的一種,它是指標中只指向棧區的且指標的移動範圍是有限的,即陣列長度。而且陣列在定義之初就已經有了自己的記憶體,一般的指標如果未指向某一個記憶體塊時,它是沒有自己的記憶體的,即所謂的野指標。

聯絡:如上面所說,陣列只是定義在棧區的一個連續變數,它的首地址就是一個指標。

總結:不僅陣列有指標,所有變數都有指標,指標說白了就是記憶體中的地址,就像一個房間必須有一個房間號。在C/C++語言中定義一個指標,就是在棧區開闢一個記憶體空間用來存放它指向的記憶體地址,然後給指標賦值,就是把地址值賦值給剛才開闢的記憶體空間,然後通過存取該記憶體中的地址值來間接存取該地址下存放的資料。如果該地址值指向的是一塊靜態儲存區,如字串常數等,當然就不可以修改指向的內容啦。

陣列指標

定義 int (*p)[n];
()優先順序高,首先說明p是一個指標,指向一個整型的一維陣列,這個一維陣列的長度是n,也可以說是p的步長。也就是說執行p+1時,p要跨過n個整型資料的長度。
大小:一個int型指標長度的空間
如要將二維陣列賦給一指標,應這樣賦值:
int a[3][4];
int (*p)[4]; //該語句是定義一個陣列指標,指向含4個元素的一維陣列。
p=a; //將該二維陣列的首地址賦給p,也就是a[0]或&a[0][0]
p++; //該語句執行過後,也就是p=p+1;p跨過行a[0][]指向了行a[1][]

所以陣列指標也稱指向一維陣列的指標,也稱行指標。

指標陣列

定義 int p[n];
[]優先順序高,先與p結合成為一個陣列,再由int
說明這是一個整型指標陣列,它有n個指標型別的陣列元素。這裡執行p+1時,則p指向下一個陣列元素,這樣賦值是錯誤的:p=a;因為p是個不可知的表示,只存在p[0]、p[1]、p[2]…p[n-1],而且它們分別是指標變數可以用來存放變數地址。但可以這樣 p=a; 這裡p表示指標陣列第一個元素的值,a的首地址的值。
大小:n個int *的資料空間
如要將二維陣列賦給一指標陣列:
int *p[3];
int a[3][4];
p++; //該語句表示p陣列指向下一個陣列元素。注:此陣列每一個元素都是一個指標
for(i=0;i<3;i++)
p[i]=a[i]
這裡int *p[3] 表示一個一維陣列記憶體放著三個指標變數,分別是p[0]、p[1]、p[2]
所以要分別賦值。

函數指標

什麼是函數指標?

函數指標大家瞭解一下就行了,用得不多,但一定要認識它。
什麼是函數指標

如果在程式中定義了一個函數,那麼在編譯時系統就會為這個函數程式碼分配一段儲存空間,這段儲存空間的首地址稱為這個函數的地址。而且函數名錶示的就是這個地址。既然是地址我們就可以定義一個指標變數來存放,這個指標變數就叫作函數指標變數,簡稱函數指標。

那麼這個指標變數怎麼定義呢?雖然同樣是指向一個地址,但指向函數的指標變數同我們之前講的指向變數的指標變數的定義方式是不同的。例如:
int(*p)(int, int);

這個語句就定義了一個指向函數的指標變數 p。首先它是一個指標變數,所以要有一個「*」,即 ( *p);

其次前面的 int 表示這個指標變數可以指向返回值型別為 int 型的函數;後面括號中的兩個 int 表示這個指標變數可以指向有兩個引數且都是 int 型的函數。所以合起來這個語句的意思就是:定義了一個指標變數 p,該指標變數可以指向返回值型別為 int 型,且有兩個整型引數的函數。p 的型別為 int(*)(int,int)。

所以函數指標的定義方式為:
函數返回值型別 (* 指標變數名) (函數參數列);

「函數返回值型別」表示該指標變數可以指向具有什麼返回值型別的函數;「函數參數列」表示該指標變數可以指向具有什麼參數列的函數。這個參數列中只需要寫函數的引數型別即可。

我們看到,函數指標的定義就是將「函數宣告」中的「函數名」改成「(*指標變數名)」。但是這裡需要注意的是:「(*指標變數名)」兩端的括號不能省略,括號改變了運運算元的優先順序。如果省略了括號,就不是定義函數指標而是一個函數宣告了,即宣告了一個返回值型別為指標型的函數。

那麼怎麼判斷一個指標變數是指向變數的指標變數還是指向函數的指標變數呢?首先看變數名前面有沒有「」,如果有「」說明是指標變數;其次看變數名的後面有沒有帶有形參型別的圓括號,如果有就是指向函數的指標變數,即函數指標,如果沒有就是指向變數的指標變數。

最後需要注意的是,指向函數的指標變數沒有 ++ 和 – 運算。

注意:函數指標的型別一定要與所指函數的型別相同(函數的返回值),形參型別也要相同,當一個函數指標指向一個函數時就能像使用函數一樣使用它。

範例:

#include<stdio.h>
int fun(int Num1, int Num2)
{
	return Num1 > Num2 ? Num1 : Num2;
}
int main(void)
{
	int (*p)(int, int);
	p = fun;
	printf("66和88中最大的是:%d ", p(66, 88));
	
	return 0;
}

執行結果如圖:

在這裡插入圖片描述

動態陣列

在實際程式設計中,有些陣列的個數並不能確定,如果定義得陣列過大,浪費記憶體空間,如果定義得 太小,又容納不下。也就是說,用靜態陣列的方法很難解決。那麼,如何解決這個問題呢? 因為陣列名代表了該陣列的首地址,也就是指標,如果定義一個指標表示陣列名,之後將一段記憶體 空間的地址賦給該指標,就可以實現動態陣列啦!
為了實現動態陣列,必須能夠動態申請記憶體空間。C語言提供了一些記憶體管理函數,這些函數可以 根據需要動態地申請記憶體空間,以實現動態陣列的要求。

實現動態陣列的相關函數

malloc()函數

分配若干個位元組的空間,返回一個指向該區域的指標。若系統不能提供足夠大的記憶體空間,或者初始的指向不明確,那就鐵定返回NULL,當然了,設計指標問題錯的太離譜了,直接彈出黃框框警告。
malloc()的原型為:
void malloc(unsigned int size),size表示向系統申請的空間大小,呼叫成功將返回一個指向void型別的指標void,常用來作為一個萬金油指標,和函數裡面求導類似,不管會不會,首先去求導。
指標本質是一個被儲存著的地址,過去講過記憶體中劃分為了若干個區域,各種資料型別的值都可以分一塊上去,這個區域近似於無限大,說這句話,就是要把所謂的short,int,char看作不同型別的地址,類似於不同的學區,其依託的劃片學校不同。
廢話這麼多,還是要體會到,同種型別的指標才能彼此賦值。如果要呼叫malloc的返回值賦值給某個指標,應該先根據該指標的基本類型,採用一種叫做強制型別轉換的方式,將malloc返回的型別不明確指標,

malloc()函數的用法:
原型:void "malloc(unsigned size)

在記憶體的動態儲存區分配n個長度為size的連續空間。
malloc()函數的返回值
申請成功,則返回新分配記憶體塊的起始地址;否則,返回NULL。
注意: malloc()函數的返回值是一個無型別指標,可以指向任何型別的資料。在實際使用時,需將malloc()函 數的返回值強制轉換成被賦值指標變數的資料型別,以免出錯。

舉個例子:

    int *p=NULL;
    scanf("%d",&n);
    p=(int *)malloc(n*sizeof(int));//申請n個sizeof個位元組的儲存空間,也叫做記憶體吧,注意這個強制型別轉化!

free()函數
釋放malloc分配的儲存空間,原型為 void free(void *p),該函數的功能是是釋放動態申請的由指標P指向的儲存空間,該函數無返回值。free()中引數給出的地址是函數malloc申請空間時候返回的地址,free執行後,以前分配的由指標P指向的記憶體被清空。
Lp=(int *)malloc(sizeof(int));
free(Lp);
比方說這個組合就是一對的數值,成對出現,按照百度的解釋,free讓動態資料記憶體結構變的真的可以動態,否則就是個偽動態,只能申請,不能釋放。
標準庫中malloc函數的實現原理。要了解針對malloc的記憶體儲存結構,malloc不像全域性變數一樣,不是在編譯器編譯的時候就會分配記憶體空間,而是在呼叫到malloc函數時才會分配空間。有時還會中途呼叫free函數釋放空間出來。
malloc是從堆區申請空間,函數結束後不會自動釋放,如果不人為地釋放的話,要等到程式結束後,系統才會自動回收
malloc用於向系統申請一定數量的記憶體,如果你的程式一味的申請記憶體供自己使用,那麼系統可分配給其它程式的記憶體就會減少,到最後無記憶體可用,最終導致系統執行緩慢,不穩定等問題。顯然,這種只索取不奉獻的行為是不可取的因此,C語言提供了free函數,用於向系統返還借用的記憶體。有借有還,再借不難。

free()函數的用法

原型: void free(void *ptr)
free()函數的功能
釋放由ptr指向的記憶體塊(ptr是呼叫malloc()函數的返回值)。
free()函數的返回值:無
注意: 使用malloc()函數申請的記憶體塊,操作結束後應及時使用free()函數釋放。尤其是迴圈使 用malloc()函數時,如果不及時釋放不再使用的記憶體塊,很可能很快就耗盡系統的記憶體資源,從而導致 程式無法繼續執行。

範例:

//這裡寫個求平均分的程式碼
#include<stdio.h>
#include<stdlib.h>   //使用malloc和free需要包含此標頭檔案
int main(void)
{
	int Num, i;
	float Sun = 0;
	float* Lp;
	printf("請輸入學生人數:");
	scanf("%d", &Num);
	Lp = (float *)malloc(sizeof(float) * Num);
	if (Lp == NULL)
	{
		printf("申請記憶體失敗!");
		return -1;
	}
	for (i = 0; i < Num; i++)
	{
		printf("請輸入第%d名學生的成績:", i + 1);
		scanf("%f", &Lp[i]);
	}

	for (i = 0; i < Num; i++)
	{
		Sun += Lp[i];
	}
	free(Lp);
	printf("同學的平均分為:%.2f 分", Sun / Num);
}

結果如同:
在這裡插入圖片描述

注意: 申請成功後可以像使用普通陣列一樣使用動態陣列!

下面使用C++來實現動態陣列(如果沒有學過C++可以跳過)

new 和 delete 是 C++ 用於管理 堆記憶體 的兩個運運算元,對應於 C 語言中的 malloc 和 free,但是 malloc 和 free 是函數,new 和 delete 是運運算元。除此之外,new 在申請記憶體的同時,還會呼叫物件的建構函式,而 malloc 只會申請記憶體;同樣,delete 在釋放記憶體之前,會呼叫物件的解構函式,而 free 只會釋放記憶體。

new的用法

1.開闢單變數地址空間

使用new運運算元時必須已知資料型別,new運運算元會向系統堆區申請足夠的儲存空間,如果申請成功,就返回該記憶體塊的首地址,如果申請不成功,則返回零值。

new運運算元返回的是一個指向所分配型別變數(物件)的指標。對所建立的變數或物件,都是通過該指標來間接操作的,而動態建立的物件本身沒有識別符號名。

一般使用格式:
格式1:指標變數名=new 型別識別符號;
格式2:指標變數名=new 型別識別符號(初始值);
格式3:指標變數名=new 型別識別符號 [記憶體單元個數];

說明:格式1和格式2都是申請分配某一資料型別所佔位元組數的記憶體空間;但是格式2在記憶體分配成功後,同時將一初值存放到該記憶體單元中;而格式3可同時分配若干個記憶體單元,相當於形成一個動態陣列。例如:

1.new int;  //開闢一個存放整數的儲存空間,返回一個指向該儲存空間的地址。int *a = new int 即為將一個int型別的地址賦值給整型指標a
2.int *a = new int(5) 作用同上,但是同時將整數空間賦值為5

2.開闢陣列空間

對於陣列進行動態分配的格式為:
   指標變數名=new 型別名[下標表示式];
   delete [ ] 指向該陣列的指標變數名;

兩式中的方括號是非常重要的,兩者必須配對使用,如果delete語句中少了方括號,因編譯器認為該指標是指向陣列第一個元素的指標,會產生回收不徹底的問題(只回收了第一個元素所佔空間),加了方括號後就轉化為指向陣列的指標,回收整個陣列。

delete []的方括號中不需要填陣列元素數,系統自知。即使寫了,編譯器也忽略。

請注意「下標表示式」不必是常數表示式,即它的值不必在編譯時確定,可以在執行時確定。

一維: int *a = new int[100];    //開闢一個大小為100的整型陣列空間

二維: int **a = new int[5][6]

三維及其以上:依此類推.

一般用法: new 型別 (初值)

delete的用法

  1. 刪除單變數地址空間

    int *a = new int;
    
    delete a;   //釋放單個int的空間
    
  2. 刪除陣列空間

    int *a = new int[5];
    
    delete []a;    //釋放int陣列空間
    

三、使用注意事項

  1. new 和delete都是內建的操作符,語言本身所固定了,無法重新客製化,想要客製化new和delete的行為,徒勞無功的行為。

  2. 動態分配失敗,則返回一個空指標(NULL),表示發生了異常,堆資源不足,分配失敗。

  3. 指標刪除與堆空間釋放。刪除一個指標p(delete p;)實際意思是刪除了p所指的目標(變數或物件等),釋放了它所佔的堆空間,而不是刪除p本身(指標p本身並沒有復原,它自己仍然存在,該指標所佔記憶體空間並未釋放),釋放堆空間後,p成了空指標。

  4. 記憶體漏失(memory leak)和重複釋放。new與delete 是配對使用的, delete只能釋放堆空間。如果new返回的指標值丟失,則所分配的堆空間無法回收,稱記憶體漏失,同一空間重複釋放也是危險的,因為該空間可能已另分配,所以必須妥善儲存new返回的指標,以保證不發生記憶體漏失,也必須保證不會重複釋放堆記憶體空間。

  5. 動態分配的變數或物件的生命期。我們也稱堆空間為自由空間(free store),但必須記住釋放該物件所佔堆空間,並只能釋放一次,在函數內建立,而在函數外釋放,往往會出錯。

  6. 要存取new所開闢的結構體空間,無法直接通過變數名進行,只能通過賦值的指標進行存取。

    用new和delete可以動態開闢和復原地址空間。在程式設計序時,若用完一個變數(一般是暫時儲存的資料),下次需要再用,但卻又想省去重新初始化的功夫,可以在每次開始使用時開闢一個空間,在用完後復原它。

下面使用new和delete來實現動態陣列:

//這裡寫個求平均分的程式碼
#include<iostream>
using namespace std;
int main(void)
{
	int Num, i;
	float Sun = 0;
	float* Lp;
	cout << "請輸入學生人數:";
	cin >> Num;
	Lp = new float[Num];
	if (Lp == NULL)
	{
		printf("申請記憶體失敗!");
		return -1;
	}

	for (i = 0; i < Num; i++)
	{
		cout<<"請輸入第"<<i+1<<"名學生的成績:";
		cin >> Lp[i];
	}

	for (i = 0; i < Num; i++)
	{
		Sun += Lp[i];
	}
	cout.precision(4);
	cout << "同學的平均分為:" << Sun / Num << " 分" << endl;
}

執行結果如圖:
在這裡插入圖片描述
本篇到此結束。如果本篇中有什麼錯誤或者需要補充的地方歡迎大家在評論區留言,謝謝大家!
如果遇到什麼問題歡迎大家進群討論或者加我qq
群內也有各種學習資料,歡迎大家一起來學習!
qq:846581636
qq群:759252814
期待你的關注
感謝大家的支援,謝謝!