指標是C語言一個重要的概念,也是C語言的一個特色,正確的使用指標,可以使程式簡潔、緊湊、高效。
指標:是一個特定的型別資料的儲存地址,如一個變數的地址。
兩種儲存變數的方式:直接儲存和間接儲存。
直接儲存:按變數名儲存,在程式中定義的變數,編譯時系統為其分配記憶體單元。
間接儲存:使用指標,將變數的地址儲存賦給指標儲存。
void main(){
int i = 100;
int *p = &i;
printf("這是i的地址:%#x\n 這是p的值:%#x\n", &i, p);
printf("i的值:%d\n", *p);
getchar();
}
複製程式碼
從執行結果我們看到了指標p儲存的時候 i 的地址,*p得到的值是i的值100.
指標是特定資料型別的儲存地址,所以指標有資料型別的,但是地址是沒有型別的。 如上面的程式中,指標的型別是int型別
void main(){
int i = 100;
int *p = &i;
printf("這是i的地址:%#x\n 這是p的值:%#x\n", &i, p);
printf("i的值:%d\n", *p);
double j = 23.4;
p = &j;
printf("p:%#x, %lf\n",p,*p);
getchar();
}
複製程式碼
上面程式中最終得到的值是0.0000,這是因為指標賦值為double型別變數的地址,而通過sizeof(int)位元組讀取sizeof(double)位元組變數的值,是不允許的。這裡我們可以知道地址只是開始的位置,型別讀取到什麼位置結束。
懸空指標
如果一個指標變數,既沒有賦NULL值,也沒有指向有效的記憶體地址,則成為懸空指標。懸空指標的值是不確定的,直接操作導致系統崩潰,所以應該避免懸空指標的使用,定義指標變數的時候就要初始化。
NULL空指標
void main(){
int i = 100;
int *p = NULL;
p = &i;
printf("\n\n\n i的值%d",*p);
getchar();
}
複製程式碼
上面程式 p = NULL就是空指標。給一個指標賦予NULL值,NULL是一個指標值,任何型別的指標都可以賦予該值。
指標的兩個特殊運算子*和&
&:取地址運算子,返回操作物件的記憶體地址
*:間接訪問運算子,取指標所指單元的值。
多級指標
指標儲存的是變數的地址,儲存的這個變數還可以是一個指標變數
void main(){
int i = 100;
int* p1 = NULL;
//儲存i的地址
p1 = &i;
//儲存p1的地址
int** p2 = &p1;
//儲存p2的地址
int*** p3 = &p2;
printf("\n\n\n p1:%#x\n p2:%#x\n p3:%#x\n",p1,p2,p3);
getchar();
}
複製程式碼
指標的運算
指標的運算,一般在陣列遍歷時才有意義,基於陣列在記憶體中線性排列的方式。
void main(){
//陣列在記憶體中連續儲存
int a[] = {10,20,30};
//陣列變數名:a就是陣列的首地址
int *p = a;
printf("\na:%#x\n",a);
printf("&a:%#x\n",&a);
printf("&a[0]:%#x\n",&a[0]);
printf("p:%#x\n", p);
printf("開始*p:%d\n", *p);
//指標的自增,向前移動sizeof(資料型別)個位元組
p++;
printf("p++後:%d\n", *p);
//指標的自減
p--;
printf("p--後:%d\n", *p);
getchar();
}
複製程式碼
自增1或者自減1運算使指標值增加或者減少所指資料型別的長度值。 指向同一陣列不同元素的指標可以進行相減操作,結果為兩個指標之間相差元素的個數。
通過指標給陣列賦值
void main(){
int a[5];
int *p = a;
int i = 0;
for (;p < a+5; p++)
{
*p = i;
i++;
}
p = a;
for (int j = 0; j < 5; j++)
{
printf("\n %d\n", *p);
p++;
}
getchar();
}
複製程式碼
函式指標
int add(int* a, int* b){
return *a + *b;
}
void main(){
int a, b;
scanf("\n%d\n", &a);
scanf("\n%d\n", &b);
/*
函式指標
函式返回值型別,函式指標的名稱,函式的引數列表
*/
int(*func_add)(int* a, int* b) = add;
int rs = func_add(&a, &b);
printf("add result:%#d\n",rs);
getchar();
}
複製程式碼
int add(int a,int b){
return a + b;
}
int minus(int a,int b){
return a - b;
}
//msg函式需要傳遞一個函式指標引數
//類似於我們Java中的回撥函式
void msg(int(*func_p)(int a, int b), int m, int n){
printf("執行回撥函式...\n");
int r = func_p(m, n);
printf("執行結果:%d\n",r);
}
void main(){
//加法
msg(add, 3, 3);
//減法
msg(minus, 5, 1);
getchar();
}
複製程式碼