1. 程式人生 > >一文搞懂C/C++中指標那些事(上篇)

一文搞懂C/C++中指標那些事(上篇)

一 指標變數

1.間接存取
       指標變數的值為地址;普通變數的值為資料;其中“*”為指標運算子。&是地址操作符,用來引用一個記憶體地址。通過在變數名字前使用&操作符,我們可以得到該變數的記憶體地址。
       針對記憶體資料的存取的兩種方法:直接存取和間接存取,所謂的間接存取是指為了存取一個變數值,首先從存放變數地址的指標變數單元中取得該變數的儲存地址,然後再從該地址中存取該變數值。直接上例子:

int x,*s; //定義了整形變數x;還定義了一個用於存放整形變數所佔記憶體地址的指標變數s
s = &x;   //將x所佔的記憶體地址取出賦給指標變數s
*s = 3
; //在s所指向的記憶體地址中賦以整型值3 //等價於 int x; x = 3;

2.指標變數定義與引用
       一般形式: 型別識別符號 *指標變數名

int *m,*n;
double *p,*q;
int *uninit;    // int指標未初始化
int *nullptr = NULL;   // 初始化為NULL
void *vptr;   // void指標未初始化

       注:C語言中,陣列元素的下標是從0開始的。
例:

int main()
{
    double x=0.11,y=0.1;
    double *p,*q;
    p=&x;q=&y
; printf("&x=%u,&y=%u\n",&x,&y); //輸出變數xy的地址 printf("p=%u,q=%u\n",p,q); //輸出指標變數存放的地址 printf("x=%f,y=%f\n",x,y); //輸出X與y的值 printf("*p=%f,*q=%f\n",*p,*q); //輸出指標變數p與q所指向的變數值,p是指標變數,不能說*p是指標變數 }

3.指標變數作為函式引數
       例:交換兩個變數值

void swap(int **a,int **b)
{
    int
*t; t = *a; *a = *b; *b = t; } int main() { int i=3,j=5; int *p = &i, *q = &j; printf("%d,%d,%d,%d\n",*p,*q,i,j); swap(&p,&q); //實參p與q的指標單元的地址傳遞給了形參a與b, printf("%d,%d,%d,%d\n",*p,*q,i,j); getchar(); }

4.指向指標的指標
       指向指標的指標就是指向指標變數的指標。

int x,*q,**p;
q = &x;
p = &q;
**p = 3;
//等價於
int x; x=3

       例:交換變數的值

void swap(int **a,int **b)
{
    int *t;
    t = *a;
    *a = *b;
    *b = t;
}
int main()
{
    int i=3,j=5;
    int *p = &i, *q = &j;
    printf("%d,%d,%d,%d\n",*p,*q,i,j);
    swap(&p,&q);  //實參p與q的指標單元的地址傳遞給了形參a與b,
    printf("%d,%d,%d,%d\n",*p,*q,i,j);
    getchar();
}

       總結:這裡可以把指標、引用和值的關係類比為信封、郵箱地址和房子。一個指標就好像是一個信封,我們可以在上面填寫郵寄地址。一個引用(地址)就像是一個郵件地址,它是實際的地址。取值就像是地址對應的房子。我們可以把信封上的地址擦掉,寫上另外一個我們想要的地址,但這個行為對房子沒有任何影響。

二 指標陣列

       指標陣列定義如下:型別標識 *陣列名[陣列長度說明]
       例如: int *p[4];

int main()
{
    int a[5]={1,2,3,4,5};
    int *num[] = {&a[0],&a[1],&a[2],&a[3],&a[4]};
    int **p,k;
    p = num;  //等價於p=&num[0]
    for(k=0;k<5;k++)
    {
        printf("%5d",**p);
        p++;
    }
    printf("\n");
    getchar();
}

程式執行結果 : 1 2 3 4 5
       以下四個說明語句是等價的:

int a[10],*p=a;
int a[10],*p=&a[0];
int a[10],*p; p=a;
int a[10],*p; p=&a[0];

三 指標與結構體

       就像陣列一樣,指向結構體的指標儲存了結構體第一個元素的記憶體地址。與陣列指標一樣,結構體的指標必須宣告和結構體型別保持一致,或者宣告為void型別。

struct person {
  int age;
  char *name;
};
struct person first;
struct person *ptr; 
first.age = 26;
char *fullname = "full name";
first.name = fullname;
ptr = &first; 
printf("age=%d, name=%s\n", first.age, ptr->name);

第1至6行聲明瞭一個person結構體,一個變數指向了一個person結構體和指向person結構體的指標。
第8行為age成員賦了一個int值。
第9至10行我們聲明瞭一個char指標並賦值給一個char陣列並賦值給結構體name成員。
第11行我們把一個person結構體引用賦值給結構體變數。
第13行我們列印了結構體例項的age和name。這裡需要注意兩個不同的符號,’.’ 和 ‘->’ 。結構體例項可以通過使用 ‘.’ 符號訪問age變數。對於結構體例項的指標,我們可以通過 ‘->’ 符號訪問name變數。也可以同樣通過(*ptr).name來訪問name變數。