C/C++,指標的定義和使用
概述
C語言中的指標是專門用來存放記憶體地址的變數。每個指都有一個與之相關聯的資料型別,該型別決定了指標指向的資料的型別。
C語言中使用*把一個識別符號宣告為一個指標,指標定義的一般形式為:
資料型別 *指標變數名;
例如:
char *pc;
int *pi;
doule *pd = NULL;
第三行定義了一個指標並初始化為NULL,表示該指標不指向任何變數。
注意:第一行和第二行定義的指標未初始化,這是相當危險的。因為未初始化的指標隨機指向記憶體中一個地址,對該地址空間的寫操作其後果不能確定,所以應避免使用未初始化的指標,在定義指標時最好將它初始化為NULL。
與指標相關的兩個運算子:
& 取地址運算子
* 取指標指向的記憶體單元的值
指標和陣列
陣列名實際上就是指向陣列第一個元素的指標。
例1:以不同方式輸出陣列所有元素的值
#include <stdio.h>
int main()
{
int a[10], i, *p = NULL;
for (i = 0; i < 10; i++)
a[i] = i;
for (i = 0; i < 10; i++)
printf("%d ", a[i]);
printf("\n" );
for (i = 0; i < 10; i++)
printf("%d ", *(a + i));
printf("\n");
for (p = a; p < a +10; )
printf("%d ", *p++);
printf("\n");
return 0;
}
說明:表示式p++,++和的優先順序相同,結合方式為自左向右,因此等價於*(p++)。
注意:不能對陣列名執行++、–操作,比如a++是不合法的,因為a是陣列的首地址,它的值在程式執行過程中是固定不變的,是常量。
陣列元素也可以是指標型別,這種陣列稱為指標陣列。
指標陣列定義的一般形式為:
資料型別 *陣列名[陣列長度];
說明:*的優先順序低於[]。
例2:指標陣列和二級指標
#include <stdio.h>
int main()
{
int a[5] = {1, 3, 5, 7, 9};
/*int *pi[5] = {NULL, NULL, NULL, NULL, NULL}, i;*/
int *pi[5], i;
int **pp = pi;
for (i = 0; i < 5; i++){
pi[i] = &a[i];
printf("%d ", *pi[i]);
}
printf("\n");
for (i = 0; i < 5; i++, pp++)
printf("%d ", **pp);
printf("\n");
return 0;
}
例3:陣列指標
#include <stdio.h>
void print_arr(int (*p)[])
{
int i;
for (i = 0; i < 5; i++)
printf("%d ", (*p)[i]);
printf("\n");
}
int main()
{
int a[2][5] = {1, 3, 5, 7, 9, 2, 4, 6, 8, 0};
int (*p)[5] = a;
print_arr(p);
p++;
print_arr(p);
return 0;
}
注意:區別int (*p)[5]和int *p[5],前者是一個指標,指向包含5個元素的陣列。後者是一個數組,長度為5,陣列中每個元素指向一個整形變數。
指標和函式
指向函式的指標
指向函式的指標是一個指標變數,它指向一個函式。一個函式的函式名就是一個指標,它指向函式的程式碼。
指向函式的指標的一般定義形式為:
返回值 (*指標變數名) ()
注意:前者是返回指標的函式,它是一個函式宣告。後者是指向函式的指標,它定義了一個指標。
int *f(int i, int j);
int (*f)(int i, int j);
函式指標作為形參
例4:函式指標作為形參
#include <stdio.h>
int get_max(int i, int j)
{
return (i > j? i : j);
}
int compare(int i, int j, int k, int (*p)(int, int))
{
int ret = 0;
ret = p(i, j);
ret = p(ret, k);
}
int main()
{
int ret = 0;
ret = compare(1, 3, 5, get_max);
printf("The max is %d.\n", ret);
return 0;
}
補充:訊號處理函式將用到該知識點。
返回函式指標的函式
例5:返回函式指標的函式
#include <stdio.h>
int get_max(int i, int j)
{
return (i > j? i : j);
}
int (*get_function(int a))(int, int)
{
printf("The number is %d.\n", a);
return get_max;
}
int main()
{
int ret = 0;
int (*p)(int, int);
p = get_function(100);
ret = p(10, 15);
printf("The max is %d.\n", ret);
return 0;
}
說明:get_function函式返回了指向函式get_max的指標int(*)(int, int)。
字元指標和字元陣列的區別
例6:字元指標和字元陣列的區別
#include <stdio.h>
int main()
{
char string[] = "Linux C";
char *pc = "Linux C";
string[0] = 'A';
printf("%c\n", string[0]);
pc[0] = 'B';
printf("%c\n", pc[0]);
return 0;
}
上述程式碼的執行結果是:
# ./a.out
A
Segmentation fault (core dumped)
程序執行過程中提示“段錯誤”是因為指標pc指向的資料在記憶體空間中是隻讀(這些資料存放在.rodata段)的。