1. 程式人生 > >對C語言中指標與指標陣列的理解!

對C語言中指標與指標陣列的理解!

指標就是地址!

概念

C語言中,允許用一個變數來存放地址,這種變數稱為指標變數。一個指標變數的值就是某個記憶體單元的地址。指標變數就是用來存放指標(地址)的變數!

&運算子:求某一變數在儲存單元中的記憶體地址。

*運算子:取出指標變數所指向變數的內容,後面跟指標變數。

目的 

定義指標的目的就是為了通過指標去訪問儲存單元。

指標變數的定義

一般形式:  型別識別符號  *指標變數名

指標變數名前面的*號表示該變數為指標變數,它不是變數名本身的一部分。

指標變數的型別識別符號一定要與指標變數指向的地址中存放的數值型別一致。

例如

1.先定義再指向

int a=10;
int *p;
p=&a;        //p中儲存了a 的地址值,稱指標變數p指向了變數a

指標變數p的型別識別符號(int)與a中儲存的數值10對應的型別識別符號(int)一致

2.定義指標變數的同時,讓指標變數有所指(指向變數a)

//下面這種定義同上面是一樣的 
int a=10;
int *p=&a;

指標變數的使用

1.指標變數是一個變數,它在記憶體中也會有一個記憶體地址,因此其他的指標變數也可以指向這個指標變數(其他的指標變數可以儲存該指標變數的地址值)

int a=10;
int *p=&a;  指標變數p指向了變數a(指標變數p有所指)
int **q=&p;

//int **q=&p程式碼解釋
&p:取出指標變數p的地址值
int **q 相當於 int *(*q):
        1.括號裡的*表示q是一個指標變數
        2.外面的int * 表示指標變數q指向的變數的型別是一個整型(int)的指標變數

2.指標變數內只能存放其他變數的地址值,而不能直接存放一個普通的資料

int *a = 10086;    /*錯誤*/
int *b = 0;        /*正確:可以賦值0,但這個指標變數不指向任何具體的變數*/

int *c = 0x00002000;/*錯誤*/編譯器並不知道這個資料是一個地址值,因為你沒有告訴它

int *d = (int *)0x00002000;/*正確*/將0x00002000轉換為int型別指標(int型別地址)
使用的前提是你確定這個記憶體確實可以使用,不然對該地址的內容進行操作時, 會出現引用非法指標的錯誤,導致程式崩潰。

怎麼告訴編譯器這個資料是一個地址值呢? 

1.使用&運算子,但&運算子只能取一個變數的記憶體地址,它取不了一個常數的記憶體地址,所以只能使用2方法

2.將這個資料強制型別轉換為某個資料型別的指標

指標與字串 

char *string="hello";    //指標變數string儲存的是字串的首地址
printf("%s",string);

列印結果:hello
輸出指標變數的寫法是string,而不是*string!
char *string="hello";    //指標變數string儲存的是字串的首地址
printf("%s",(void*)string);

列印結果:"hello"的地址值
將string強制轉化為void指標型別,就可以輸出地址值,而不是資料值

當輸出字元型別的指標時,這個指標顯示的是該指標所指向的資料內容,而不是該資料的地址。一定要注意,只有字元型別的指標才會這樣,其他型別的指標顯示的是地址,而不是資料。原因:C格式的字串是通過字元的指標定義的。

例子:

int a[3]={1,2,3};
int *string = a;
printf("%s\n",string);
printf("%S\n",*string);

列印結果:
陣列a的記憶體地址
1
強調:只有指向字元型別的指標變數才能使用printf("%s",string)輸出資料,而不是地址值

指標陣列 

 若一個數組的元素型別為指標,則稱該陣列為指標陣列(陣列中所有元素儲存的都是地址值)

char *string[]={
                "張三",
                "李四",
                "王五"
                };
printf("%s\n",string[0]);
printf("%s\n",string[1]);
printf("%s\n",string+[2]);

列印結果:
張三
李四
王五

理解:string是一個字串陣列,string[0]儲存的是"張三"的地址值,因為它是字元型的指標變數,
所以可以直接使用printf("%s\n",string[0])輸出資料,而不是地址
請參考指標與字串