1. 程式人生 > >C/C++,指標的定義和使用

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段)的。