1. 程式人生 > >C語言學習總結----指標

C語言學習總結----指標

指標,指標變數,變數指標

指標: 記憶體單元的地址。
指標變數:存放地址(指標)的變數。
變數指標:變數的地址。
指標是一個無符號整數取值範圍(0—2^32-1),由機器的定址能力所決定,任何指標在32位機器平臺下佔4個位元組,在64位平臺下佔8個位元組,這個我們可以使用關鍵字sizeof(指標)來測試!
在這裡插入圖片描述

通常人們所講的指標其實是指標變數,如定義一個指標,其實是定義一個指標變數。

為什麼要有指標呢?

指標是C語言的靈魂!眾所周知,資料是在記憶體中存放的,不同型別的資料所佔位元組數的多少不同,為了正確地訪問這些資料,因此為每個位元組都編上號碼,就像門牌號、身份證號一樣,每個位元組的編號是唯一的,根據編號可以準確地找到某個位元組。簡單來講指標的作用就是快速準確定位和查詢!

常見的指標型別

字元指標:兩種用法:
1.單個字元的地址

int main()
{
	char ch = 'h';
	char* pch = &ch;
	return 0;
}

2.字串首元素的地址

int main()
{
	char* str = "hello";//str中儲存的是首元素h的地址
	return 0;
}

二級指標 (指標的指標)

int main()
{
	int a = 3;
	int* pa = &a;    //一級指標
	int** ppa = &pa; //二級指標
	return 0;
}

在這裡插入圖片描述
注:有二級指標自然也有三級指標,四級指標,把這些指標統稱為多級指標!

指標常量與常量指標

指標常量:指標型別的常量。本質是一個常量,指標的值不能被修改,但指標指向的物件的內容可以被修改。

int main()
{
	int a = 3;
	int b = 1;
	int* const p = &a;
	*p = 5;    //正確,p是一個常量,但*p不是,可以作為左值
	p = &b;    //錯誤,左值不能是常量,或者說p是常量值不能被修改
	return 0;
}

常量指標:指向常量的指標。本質是一個指標,指標的值可以被修改,但指標指向的物件的內容不能被修改。

int main()
{
	int a = 3;
	int b = 1;
	int const *p = &a;
	*p = 5;    //錯誤,*p是一個常量,不能寫入
	p = &b;    //正確
	return 0;
}

當兩者同時被const修飾呢?正如所料,p和*p的值都不能被更改!

int main()
{
	int a = 3;
	int b = 1;
	int const * const p = &a;
	*p = 5;    //錯誤,*p是一個常量,不能寫入
	p = &b;    //錯誤,p也是一個常量
	return 0;
}

如何區分呢?
主要看const修飾的是誰!簡便方法:去掉型別和變數名 將const讀作常量,*讀作指標就OK了!
小問題:陣列名屬於哪一個呢?

陣列指標和指標陣列

陣列指標:本質是一個指標,不過是指向一個數組的指標!大小自然也是4個位元組!
指標陣列:本質是一個數組:陣列的每一個元素都是指標型別,這裡的指標型別指的是同一種指標型別,畢竟陣列是同一種類型元素的集合體!
int main()
{
	int *p1[10];
	int(*p2)[10];
	return 0;
}

上面哪個是陣列指標呢?
當然是int(* p2)[10];原因是這樣的,雖然下標引用操作符的優先順序高於解引用,但是()使得p2先和 結合使得p2成為一個指標,並且這個指標指向一個含有十個整型元素的陣列。因此它是一個數組指標。
int
p2[10]呢?它是一個指標陣列,首先p2先和[]結合使得其成為一個數組,陣列中的每個元素的型別都是int*型別的,因此它是一個指標陣列!

指標運算

算術運算:對指標進行加一或減一操作可不是 簡單的進行加一或者減一。對指標加一,其實加的是其指向的型別的大小,如給整型指標加一等於加四,給字元型指標加一等於加一,給陣列指標加一,等於加一個數組的大小…
在這裡插入圖片描述

arr為陣列名,是陣列首元素的地址,即是一個整型指標,因此它加一等於加四,即指向arr[1],&arr是整個陣列的地址,即是一個數組指標,因此它加一等於加sizeof(arr)=20,所以它直接越過整個陣列的大小,指向下一個陣列的首元素。
指標減指標只有當兩個指標同時指向同一個陣列時,才允許指標減指標,減去的結果是一個有符號整數,代表兩個指標之間元素的個數。
在這裡插入圖片描述
關係運算:指標可以進行的關係運算有< <= == >= !=
注:關係運算得前提是兩個指標指向同一個陣列,否則計算是沒有任何意義的!

int main()
{
	int arr[5];
	int* p = arr;
	for (; p < &arr[5]; p++)
	{
		*p = 0;
	}
	return 0;
}
int main()
{
	int arr[5];
	int* p = arr+4;
	for (; p >= &arr[0];p--)
	{
		*p = 0;
	}
	return 0;
}

其實第二段程式碼存在一個問題,標準規定,指向陣列的指標可以與指向陣列最後一個元素後面的第一個位置的記憶體的指標相比較,但不允許與其首元素前面的記憶體空間的指標相比較!