### 指針
指針變量是用來記錄地址數據的。
只有記錄有效地址的指針才可以使用。
聲明指針變量時需要在變量名稱前加*。
/*
指針聲明演示
*/
#include <stdio.h>
int main(){
int num = 0;
int *p_num; // 聲明指針變量
p_num = # // 給指針賦值
*p_num = 10;
printf("num = %d\n", num);
return 0;
}
有效指針前加*可以表示它所捆綁的存儲區。
指針變量也分類型,不同類型的指針適合與不同類型的存儲區捆綁。
可以在一條語句里聲明多個同類型指針變量,這個時候要在每個指針變量名稱前單獨加*
/*
指針變量演示
*/
#include <stdio.h>
int main(){
int *p1, *p2;
return 0;
}
### 野指針
沒有捆綁地址的指針分為兩類:
* 1. 空指針,里面記錄空地址(NULL),這個地址的數值就是0。
* 2. 其它沒有捆綁的指針都叫做野指針。
程序中禁止出現野指針。
所有指針變量必須初始化。
指針初始化的時候*沒有參與賦值過程。
### 指針的運算
一個指針可以在不同的時候和不同的存儲區捆綁,這個時候指針代表了存儲區的某種特征。
如果指針和數組里的第一個存儲區捆綁,就可以通過這個指針找到數組里的每個存儲區。
這個時候可以認為指針間接捆綁了數組里的每個存儲區。
直接在這種指針的后面加下標就可以表示數組里的某個存儲區。
地址數據只能參與如下的幾個計算過程:
* 地址 + 整數
* 地址 - 整數
* 地址 - 地址
地址數據加減整數N實際上加減的是n個捆綁存儲的大小。
/*
指針演示
*/
#include <stdio.h>
int main(){
int arr[] = {1, 2, 3, 4, 5};
int num = 0;
int *p_arr = arr;
for (num = 0;num <= 4;num++){
printf("%d ", arr[num]);
printf("%d ", p_arr[num]);
}
printf("\n");
printf("arr + 3 = %p, arr = %p\n", arr+3, arr);
return 0;
}
數組里第一個存儲區的地址加下標可以得到下標對應存儲區的地址。
*(arr + num),這個寫法也可以代表下標為num的存儲區。
地址減地址的結果是一個整數,這個整數代表兩個地址之間包含的捆綁存儲區個數。
/*
指針演示
*/
#include <stdio.h>
int main(){
int arr[] = {1, 2, 3, 4, 5};
int *p_arr = arr;
for (p_arr = arr;p_arr <= arr + 4;p_arr++){
printf("%d ", *p_arr);
}
printf("\n");
return 0;
}
### const關鍵字
聲明指針變量的時候可以使用const關鍵字。
如果const關鍵字寫在指針聲明的類型名稱前就表示不可以通過這個指針對捆綁存儲區做賦值,但是可以對指針本身做賦值。
/*
const關鍵字演示
*/
#include <stdio.h>
int main(){
int num = 0;
const int *p_num = #
// *p_num = 10; // 編譯出錯,無法修改捆綁存儲區的值
p_num = NULL; // 可以設置指針為空指針
return 0;
}
如果const關鍵字寫在指針變量名稱前就表示不可以對這種指針做賦值,但是可以通過這個指針對它捆綁的存儲區做賦值。
/*
const關鍵字演示
*/
#include <stdio.h>
int main(){
int num = 0;
int * const p_num = #
// p_num = NULL; 錯誤
*p_num = 10;
return 0;
}
### 無類型指針
可以在聲明指針變量的時候使用void作為類型名稱,這種指針叫做無類型指針。
這種指針可以和任意類型的存儲區捆綁。
但是這種類型的指針,不能通過指針知道它所捆綁的存儲區類型是啥。
/*
無類型指針演示
*/
#include <stdio.h>
int main(){
char ch = 'u';
int num = 56;
float fnum = 6.5f;
void *p_v = NULL;
p_v = &ch;
p_v = #
p_v = &fnum;
return 0;
}
不應該在無類型指針前直接加*,也不應該用無類型指針進行加減計算,因為這些操作都是依賴于存儲區類型的,因此這些操作是不允許的。
使用無類型指針前,必須先強制類型轉換成有類型指針。
/*
無類型指針演示
*/
#include <stdio.h>
int main(){
char ch = 'u';
void *p_v = NULL;
p_v = &ch;
printf("%c\n", *(char *)p_v);
return 0;
}
無類型指針通常作為形式參數使用。
### 數組形式參數
所有的跨函數使用存儲區都是通過指針實現的。
數組做形式參數的時候,真正的形式參數都是指針。
/*
指針形式參數演示
*/
#include <stdio.h>
void print(const int *p_arr, int size){
int num = 0;
for (num = 0;num <= size - 1;num++){
printf("%d ", *(p_arr + num));
}
printf("\n");
}
int main(){
int arr[] = {1, 2, 3, 4, 5};
print(arr, 5);
return 0;
}
指針形式參數前能加const關鍵字就盡量加上。
### 指針返回值
被調用函數使用一個存儲區地址做返回值,這個時候就需要提供一個指針類型存儲區來存放這個返回值。
采用這種方法可以讓調用函數使用被調用函數的存儲區。
不可以把非靜態局部變量的地址作為返回值使用。
/*
指針演示
*/
#include <stdio.h>
int *read(void){
static int num = 0;
printf("請輸入一個數字:");
scanf("%d", &num);
return #
}
int main(){
int *p_res = NULL;
p_res = read();
printf("%d\n", *p_res);
return 0;
}