指標觀念
2008年9月8日 星期一 by Anati
我想對於C語言指標的部份一定很多的初學者一直跨不過這個阻礙,因為我也是過來人,我想對於某些部份大家可能存在著同樣的問題,由網路上和自己測式研究發現了一些知識,而且可以以理論來解釋,所以大家不妨看看,我所介紹指標的部份,指標對於C/C++真的很重要,過你越過這個關卡,我想你才算是真的懂寫C語言吧!
※ 兩個運算子
「&」
* 取址運算子 ( 取得變數的記憶體位址 )
* 參考運算子 ( 參考傳遞使用 )
「*」
* 一般運算符號
* 取值運算子 ( 將指標變數中的內容位址取出真正的內容值 )
Example:
int x = 20; (將實值20存入x這個變數空間)
int* ptr; (宣告一個指標變數(ptr is point to int))
ptr = &x; (將x的記憶體位址放入ptr指標變數中)
printf("%d %p", *ptr, ptr); (印出ptr所指向的值和ptr指標內容值)
圖解:
※ int* ptr 宣告的意義
* 中文:ptr是一個指向整數型別的指標變數
* 英文:ptr is a pointer, point to a int variable
※ 解參考寫入資料 (deference)
Example:
int y; (建立一般變數y)
int* y_ptr; (建立一個int型別的指標變數)
y_ptr = &y; (讓y_ptr指向變數y的位址)
*y_ptr = 50; (透過解參考寫入資料50)
圖解:
※ 兩個重點
* y_ptr = &y 指標一定要指定某變數的位址否則就要指定為0(null),當此指標中的變數位址是有效的時候才可以解參考。
* *y_ptr = 50 利用「*」取值反向參考變數y來指定y的內容為50
※ 指標初始嚴重錯誤
int* ptr = 100 指標內容不可指定「常數值」必須為一變數的地址,如int* ptr = &a,所以大部份指標宣告的時候都會直接指定初值,以免解參考的時候出現錯誤,因為有可能會把指標變數當成一般變數來使用,指標變數和一般變數是完全不同的變數型別,所以指標變數是指標變數,而一般存值的變數是一般變數,千萬別混在一起了。
※ 指標遞增的意義
Example:
int a;
int* ptr_int = &a; (本來的ptr_int內容值是3310)
ptr_int++; (會變成3314)
char ch;
char* ptr_char = &ch; (ptr_char內容值是3121)
ptr_char++; (會變成3122)
因為指標型態不同,因此指標+1相當於記憶體位址+1(char), +4(int), +8(double)等等,依類型的不同有所不同。
※ 指標變數的加減比較
1. 指標內容可做加減法如:int* p = &a; p = p+1 (代表記憶體位址+4,因為型別為int)
2. 兩指標內容不可相加如:int* p, * q; p = p+q (不合法記憶體位址不能相加)
3. 兩指標內容可以比大小如:if (p > q) ... (得知那個指標變數內的記憶體先後)
4. 兩指標相減稱為差值運算,用來計算陣列中有幾個元素
※ 陣列指標間的關係
Example:
int array[] = {0, 1, 2};
1. array (陣列名稱) 等同於 &array[0] (陣列第一元素位址)
2. array[] 在compiler中會視為 int* const array (為一個無法指向別的空間的常數指標,一輩子只能指向array陣列開頭)
3. array[0] 等同於 *(array+0) , array[1] 等同於 *(array+1) ..... array[n] 等同於 *(array+n)
4. array++ (嚴重錯誤) 會是個error因為 array 陣列名稱是個「常數指標」是不可以改變內容值的,只可以唯讀 *(array+0) 以此類推。
※ 指標的權限
1. 指標可讀可寫,資料可讀可寫 int* ptr
2. 指標可讀可寫,資料唯讀 const int* ptr (無法透過反參考修改指向的變數內容值)
3. 指標唯讀,資料可讀可寫 int* const ptr = &x (指標建立時一定要給初始值,具只能建立一次,未來不可以修改此指標內容指向別的變數)
4. 指標唯讀,資料唯讀 const int* const ptr (同時具有2, 3點的功能)
※ 變數型態表示讀法(重要)
Example:
const int* const array[10];
先看 const array[10] 表示有一個 10 個元素的陣列,每個元素為const,再看const int* 表這10個元素每個都是const的int指標,表示所指向的資料不能修改。
圖解:
※ 兩個運算子
「&」
* 取址運算子 ( 取得變數的記憶體位址 )
* 參考運算子 ( 參考傳遞使用 )
「*」
* 一般運算符號
* 取值運算子 ( 將指標變數中的內容位址取出真正的內容值 )
Example:
int x = 20; (將實值20存入x這個變數空間)
int* ptr; (宣告一個指標變數(ptr is point to int))
ptr = &x; (將x的記憶體位址放入ptr指標變數中)
printf("%d %p", *ptr, ptr); (印出ptr所指向的值和ptr指標內容值)
圖解:
※ int* ptr 宣告的意義
* 中文:ptr是一個指向整數型別的指標變數
* 英文:ptr is a pointer, point to a int variable
※ 解參考寫入資料 (deference)
Example:
int y; (建立一般變數y)
int* y_ptr; (建立一個int型別的指標變數)
y_ptr = &y; (讓y_ptr指向變數y的位址)
*y_ptr = 50; (透過解參考寫入資料50)
圖解:
※ 兩個重點
* y_ptr = &y 指標一定要指定某變數的位址否則就要指定為0(null),當此指標中的變數位址是有效的時候才可以解參考。
* *y_ptr = 50 利用「*」取值反向參考變數y來指定y的內容為50
※ 指標初始嚴重錯誤
int* ptr = 100 指標內容不可指定「常數值」必須為一變數的地址,如int* ptr = &a,所以大部份指標宣告的時候都會直接指定初值,以免解參考的時候出現錯誤,因為有可能會把指標變數當成一般變數來使用,指標變數和一般變數是完全不同的變數型別,所以指標變數是指標變數,而一般存值的變數是一般變數,千萬別混在一起了。
※ 指標遞增的意義
Example:
int a;
int* ptr_int = &a; (本來的ptr_int內容值是3310)
ptr_int++; (會變成3314)
char ch;
char* ptr_char = &ch; (ptr_char內容值是3121)
ptr_char++; (會變成3122)
因為指標型態不同,因此指標+1相當於記憶體位址+1(char), +4(int), +8(double)等等,依類型的不同有所不同。
※ 指標變數的加減比較
1. 指標內容可做加減法如:int* p = &a; p = p+1 (代表記憶體位址+4,因為型別為int)
2. 兩指標內容不可相加如:int* p, * q; p = p+q (不合法記憶體位址不能相加)
3. 兩指標內容可以比大小如:if (p > q) ... (得知那個指標變數內的記憶體先後)
4. 兩指標相減稱為差值運算,用來計算陣列中有幾個元素
※ 陣列指標間的關係
Example:
int array[] = {0, 1, 2};
1. array (陣列名稱) 等同於 &array[0] (陣列第一元素位址)
2. array[] 在compiler中會視為 int* const array (為一個無法指向別的空間的常數指標,一輩子只能指向array陣列開頭)
3. array[0] 等同於 *(array+0) , array[1] 等同於 *(array+1) ..... array[n] 等同於 *(array+n)
4. array++ (嚴重錯誤) 會是個error因為 array 陣列名稱是個「常數指標」是不可以改變內容值的,只可以唯讀 *(array+0) 以此類推。
※ 指標的權限
1. 指標可讀可寫,資料可讀可寫 int* ptr
2. 指標可讀可寫,資料唯讀 const int* ptr (無法透過反參考修改指向的變數內容值)
3. 指標唯讀,資料可讀可寫 int* const ptr = &x (指標建立時一定要給初始值,具只能建立一次,未來不可以修改此指標內容指向別的變數)
4. 指標唯讀,資料唯讀 const int* const ptr (同時具有2, 3點的功能)
※ 變數型態表示讀法(重要)
Example:
const int* const array[10];
先看 const array[10] 表示有一個 10 個元素的陣列,每個元素為const,再看const int* 表這10個元素每個都是const的int指標,表示所指向的資料不能修改。
圖解: