1. 程式人生 > >【c語言】帶你真正走進指標的世界——指標的特性

【c語言】帶你真正走進指標的世界——指標的特性

         當你看到這篇文章時,請忘掉你之前對指標的所有認知,什麼地址什麼的統統忘掉。

                                    我來給你們重新構造一個全新的指標世界。

 首先,我們知道,c語言中有很多種變數型別

int a ; 
short b;
char c;
 .
 .
 .

  而c語言中還有一種,可以在變數後加一個符號 “ *

” 成為一種全新的變數

int* a;
short* b;
char* c;

  這個變數就是c語言中的指標變數,指標的定義就是這麼簡單,不像網上或者某些書本上故弄玄虛地說著指標的定義

好像故意把我們往錯誤的道路使勁推似的......,其實指標並不難理解,下面由我來給大家解釋下指標的特性~

                                                                    我們經常以這樣的方式給變數賦值

                                                                                 

                                         而事實上,我們這樣的賦值寫法只是一個簡略寫法

,真正的賦值寫法應該是這樣子的

                                                                                  

然而,雖然我們用的是簡略寫法,但是編譯器是允許我們這樣做的,然而,在給指標賦值時,就必須用完整的賦值方法

                                                       如上圖為使用簡略寫法賦值,編譯器報錯

                                                        圖上為使用詳細寫法後的賦值,編譯通過

既然在變數之後加上 “ * ” 可以變成一個新的變數,那麼就可以2個或者無數個 “ * ” 來宣告更多的新變量了~

                                                                               編譯安全通過~~

                                        

                    

                                                      討論完如何給指標賦值之後我們討論下指標的寬度

#include <stdio.h>
#include <string.h>

int main()
{
	char* a;
	short* b;
	int* c;

	a = (char*)1;
	b = (short*)2;
	c = (int*)3;

	return 0;
}


                                                                                 我們以上面程式碼為例

          眾所周知,當圖上的變數 a、b、c 分別為char、short、int 時,所佔據的位元組數分別是1byte、2byte、4byte,而當我們在這些變數之後加上 “ * ” 時,所佔據的位元組數是否有所變化?

                                                                 

        我們把c語言轉換成組合語言可以看出,三個指標變數雖然宣告不同,但是都是同樣佔據4位元組

        那麼我們的符號 “ * ” 如果不止一個的話搜佔據的位元組也是一樣的嗎?

                                                                         我們以此程式碼為例

                                                

       由c語言轉匯編語言可得知,帶 “ * ” 型別的變數寬度永遠都是4位元組,無論什麼型別,無論有多少個 “ * ”

                                                                      當我們看到這樣的一個程式時

#include <stdio.h>
#include <string.h>

int main()
{
	char a;
	short b;
	int c;

	a = 100;
	b = 100;
	c = 100;

	a++;
	b++;
	c++;

	printf("%d %d %d",a,b,c);

	return 0;
}



                                                                         很容易就可以得出這樣的結果

                             

                                                                        而當代碼改為 指標 自增一

#include <stdio.h>
#include <string.h>

int main()
{
	char* a;
	short* b;
	int* c;

	a = (char*)100;
	b = (short*)100;
	c = (int*)100;

	a++;
	b++;
	c++;

	printf("%d %d %d\n",a,b,c);

	return 0;
}



                                                                          得出的結果卻是這樣的

                     

                                       原因是因為:指標和常變數的計數方法不同,指標的加減法原則如下

所以,圖上程式碼中的 a 為char* 型別的變數,其值為 100 ,當自增一時,去掉符號 “*” 後剩下 char 型別,而 char 型別是 1位元組 的,所以是 100+1 = 101

再者,圖上程式碼中的 c 為 int* 型別的變數,其值為 100 ,當自增一時,去掉符號 “*” 後剩下 int 型別,而 int 型別是 4位元組 的,所以是 100+4 = 104

                                                                           而當代碼是下面這個樣子的話

#include <stdio.h>
#include <string.h>

int main()
{
	char** a;
	short** b;
	int** c;

	a = (char**)100;
	b = (short**)100;
	c = (int**)100;

	a++;
	b++;
	c++;

	printf("%d %d %d\n",a,b,c);

	return 0;
}



                                                                                 得到的結果是這樣的                  

                            

這是因為程式碼中的 a 為char** 型別的變數,其值為 100 ,當自增一時,去掉符號 “*” 後剩下 char* 型別,而 char 型別是 4位元組 的,所以是 100+4 = 104

                                                另外兩個變數推理類似,所以,當是指標加上其他整數時

#include <stdio.h>
#include <string.h>

int main()
{
	char* a;
	short* b;
	int* c;

	a = (char*)100;
	b = (short*)100;
	c = (int*)100;

	a = a+5;
	b = b+5;
	c = c+5;

	printf("%d %d %d\n",a,b,c);

	return 0;
}



                                                                                     其結果為:

                   

由上面的推理可得知:程式碼中的 c 為int* 型別的變數,其值為 100 ,當+5時,去掉符號 “*” 後剩下 int 型別,而 int 型別是 4位元組 的,所以是 100+(5X4) = 120

其他推理類似......

 

———————————————取值 “ * ” 和取址“ & ”————————————————

         當我的程式碼是在這個樣子的時候

#include <stdio.h>

int main()
{
	int x = 100;
	int* p1 = &x;

	printf("%d\n",p1);

	return 0;
}

         得到的結果是這樣的

          顯而易見,p1裡面儲存的是  X  的地址。然而,我為什麼不可以直接這樣寫呢?

#include <stdio.h>

int main()
{
	int x = 100;
	int* p1 = x;

	printf("%d\n",p1);

	return 0;
}

         編譯器尷尬又不失禮貌地回答說

        根據編譯器所給出的原因,我們可以理解到,是因為賦值符號 ” = “ 兩邊的型別不相等(一個是 int 型,一個是 int * 型別)造成的,那麼為什麼加了 ” & “ 就可以了呢? 其實在編譯器裡面 , ” & “ 有個專業名字 ,叫做取址運算子,它的作用是在型別後面自動加上一顆 ” * “ ,使得變數看起來更高大上一點~~ ,所以如果是直接的 int* p1 = x,由於 x 是 int 型別的 ,而 p1 是 int* 型別的,所以不能把 x 的值賦值給 p1 ,這個時候就需要用到 ” & “ ,在 x 的型別 int 後面加上一顆 ” * “,使得兩者型別相同,有點類似於強制轉換。

       和 “ & ” 相反的是 “ * ”,它在宣告變數時代表的是指標,但是在其他地方使用時是和 “ & ” 反過來的,它的作用是去掉一顆 “ * ” ,比如以下程式碼

#include <stdio.h>

int main()
{
	int x = 100;
	int* p1 = &x;

	printf("%d\n",*p1);

	return 0;
}

       得到的結果是

       “ * ” 在程式碼的作用是,去掉 &x 的一顆星,也就相當於去掉 “ & ” 給加上來的那顆星,就會得到 int 型別的 x ,即int 型別的 100。

       懂得以上對於指標的基本知識,即對指標的基本特已有所掌握,知道現在為止,文章還沒半個字提到地址這個概念,這是因為指標其實是做為一個c語言的變數存在,地址是它的最主要的功能,但不是全部功能,在下一篇文章中將會逐漸帶大家一步一步深入指標的世界。