1. 程式人生 > >深度剖析指標------1

深度剖析指標------1

眾所周知,指標是c語言的靈魂所在,也是c語言的難點所在,很多人在學習這部分的時候都感到非常困難,然而只要你靜下心來慢慢“品嚐”,你會發現,指標非常的靈活C語言之精髓!!

指標是什麼?這個問題聽起來真的不陌生,可能你自己都常常問你自己指標到底是什麼?
---------指標就是地址,地址就是指標


我們可以把計算機記憶體用一個方塊來模擬,把這個方塊切成若干個,每一塊大小為一個位元組(八個位元位),每一塊用一個數來標識(地址),當我們想找到某一塊時只需要知道這一塊的標識數(地址),由於這個標識數(地址)具有很強的指向性,所以我們稱它為指標。

那麼“指標變數”又是什麼呢,指標變數是我們定義的一個變數,這個變數用來存放指標
實際上,我們不要去糾結這兩個名詞,我們把指標變數一般就叫指標,區分它們並沒有實際意義。


 


一、字元指標

	char ch = 'a';
	char* p =&ch;
	printf("%c", *p); 

圖中的p就是一個字元指標,下面來看另一種常用字元指標
 

	char* p = "i love you";
	printf("%s\n", p);

這裡的p也是一個字元指標,那麼這個指標到底是啥?如果我們直接用%p打印出p,我們將得到一個地址,那麼這個地址到底是誰的地址呢?對,他就是首字元的地址,在這裡即是i的地址
下面來看一道經典例題

	char str1[] = "i love you";
	char str2[] = "i love you";
	char* str3 = "i love you";
	char* str4 = "i love you";
	if (str1 == str2)
		printf("1 and 2 is same\n");
	if (str3 == str4)
		printf("3 and 4 is same\n");

輸出結果為:3 and 4 is same
那為什麼會這樣呢?
因為這裡的str3和str4指向的是同一個字串,c/c++會把字元常量單獨放到一個區域(字元常量區),當要用到他們時,就可以用指標解引用來使用它們。理所當然,這裡的str3和str4不能再被更改否則會報錯。  str1和str2都是陣列,在C語言中,兩個陣列的地址(陣列名)怎麼可能相等呢,編譯器不可能給他們開闢在同一個地址空間,所以這裡肯定不一樣唄!!!


二、指標陣列和陣列指標


很顯然,指標陣列是陣列,    陣列指標是指標
那他們的用途分別是什麼呢?
指標陣列:
定義:

	int* arr1[10];   //存放整形指標 
	char* arr2[10];   //存放字元指標 

這裡指標陣列不再過多介紹,我們前面有一篇文章專門介紹了指標陣列和陣列指標,裡面還有一些經典例子。

陣列指標:
定義:

	int (*p1)[10]; 
	char (*p2)[10];

這裡就有一些小夥伴開始搞不清楚陣列指標和指標陣列的寫法,真的很像耶✌!!這裡有一個小訣竅來辨別他們:我們得知道[ ]的優先順序高於 * ,所以沒加括號時會與[ ]先結合,那麼他就是一個數組(指標陣列),而括號括起來後,他就是一個指標(陣列指標);

知識法寶:定義一個數組arr,區別arr和&arr
有人會一本正經的回答,它兩不就一樣嘛!確實,他倆的值都一樣,但意義卻大不相同,你需要切記:陣列名“永遠”代表陣列首元素的地址除1. 用sizeof求取它的長度  2.取地址陣列名這兩種特殊情況外)。而&arr代表這個陣列的地址。
你可以打印出 arr+1 和 &arr+1 的值,他們的值是不會相同的!!
下面看這幾條語句:

	int arr[10] = {0};
	int (*p1)[10]; 
	int (*p2)[8] = &arr;      //警告 (緯度應該一致) 
	p1 = &arr;
	p1 = arr;                 //警告  (應該取該陣列的地址,而不是首元素的地址) 

好了,那麼陣列指標一般的用途到底是啥?我們看下面的程式碼:

#include<stdio.h>
void print(int (*p)[3], int row, int col);
int main()
{
	int arr[2][3] = {{2,3,4},{5,6,7}};
	print(arr, 2, 3);
	return 0;
} 
void print(int (*p)[3], int row, int col)
{
	int i = 0;
	int j = 0;
	for (i = 0; i < row; i++)
	{
		for(j = 0; j < col; j++)
		printf("%d ", p[i][j]);
		printf("\n");
	}
}

結果為:

這是陣列指標的一個典型運用,用它來傳參多維陣列,這裡該怎樣使用它來傳參呢?
切記下面的話:

陣列 傳參 會 降維“指向其內部元素”指標

當多維陣列傳參時,用陣列名接收時,只能省去離陣列名最近的那個緯度;
 


三、指標傳參:

一級指標傳參
可以用來接收一維陣列、一級指標等等,這裡比較簡單,不再過多介紹

二級指標傳參:

下面看一段程式碼:

#include<stdio.h>
void test(char** p)
{
	printf("lalala\n");
}
int main()
{
	char c = 'b';
	char* pc = &c;
	char** ppc = &pc;
	char* arr[10];
	test(&pc);
	test(ppc);
	test(arr);
	return 0;
}

該程式碼體現了幾種二級指標的傳參(該程式碼無警告無錯誤)