一文搞懂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); //輸出變數x與y的地址
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變數。