首頁>技術>

指標被稱為是C語言的精華所在,真正理解和掌握指標是征服C語言的關鍵所在!在學習指標之前,我們先弄清楚一個概念:

地址

何謂地址?在記憶體(注意,我們這裡提到的記憶體並不是人們常說的計算機的物理記憶體,而是虛擬的邏輯記憶體空間)當中,簡單點說:地址就是可以唯一標識某一點的一個編號,即一個數字!我們都見過尺子,我們統一以毫米為單位,一把長1000毫米的尺子,其範圍區間為0~999,而我們可以準確的找到35毫米、256毫米處的位置。

同樣的道理,記憶體也如此,也是像尺子一樣線性排布,只不過這個範圍略大,在我們最廣泛使用的32位作業系統下,是從0~4,294,967,295之間,而地址就是這之中的的一個編號而已,習慣上,在計算機裡地址我們常常用其對應的十六進位制數來表示,比如0x12ff7c這樣。在我們的C程式中,每一個定義的變數,在記憶體中都佔有一個記憶體單元,比如int型別佔四個位元組,char型別佔一個位元組等等,每個位元組都在0~4,294,967,295之間都有一個對應的編號,C語言允許在程式中使用變數的地址,並可以透過地址運算子"&"得到變數的地址。

#include<stdio.h>int main(){           int i;           int a[10]={1,2,3,4,5,6,7,8,9,0};           char b[10]={'c','l','a','n','g','u','a','g','e'};           for(i=0;i<10;i++)           {                       printf("int Address:0x%x,Value:%d\n",&a[i],a[i]);          }           printf("\n");           for(i=0;i<10;i++)           {                       printf("char Address:0x%x,Value :%c\n",&b[i],b[i]);           }           return 0;}    

在32位linux系統下執行參考結果:

int Address:0xbfb949c4,Value:1int Address:0xbfb949c8,Value:2int Address:0xbfb949cc,Value:3int Address:0xbfb949d0,Value:4int Address:0xbfb949d4,Value:5int Address:0xbfb949d8,Value:6int Address:0xbfb949dc,Value:7int Address:0xbfb949e0,Value:8int Address:0xbfb949e4,Value:9int Address:0xbfb949e8,Value:0char Address:0xbfb949f2,Value :cchar Address:0xbfb949f3,Value :lchar Address:0xbfb949f4,Value :achar Address:0xbfb949f5,Value :nchar Address:0xbfb949f6,Value :gchar Address:0xbfb949f7,Value :uchar Address:0xbfb949f8,Value :achar Address:0xbfb949f9,Value :gchar Address:0xbfb949fa,Value :echar Address:0xbfb949fb,Value :

親自上機執行測試,並觀察分析結果。

指標的定義和使用

明白地址的概念之後,指標也就不奇怪了。簡單的講,地址就是邏輯記憶體上的編號,而指標雖然也表示一個編號,也是一個地址。但兩者性質卻不相同。一個代表了常量,另一個則是變數。就好比記憶體是一把尺子,而指標就是尺子上面的遊標,可以左右移動,他某一個時刻是指向一個地方的,這就是指標變數。 對指標變數定義的一般形式為: 型別說明符 *變數名; 其中,這裡的*與前面的型別說明符共同說明這是一個指標變數,型別說明符表示該指標變數所指向的變數為何種資料型別,變數名即為定義的指標變數名。除此之外,C還提供*運算子獲取地址上對應的值。 例如:

#include<stdio.h>int main(){        int num=2014;        int *p=#        printf("num Address = 0x%x,num=%d\n",&num,num);        printf("p = 0x%x,*p=%d\n",p,*p);        printf("%d\n",*&num);        return 0;}

請親自執行觀察結果並思考。值得一提的是,由於指標存放的都是地址,在32位作業系統下都在0 ~ 4,294,967,295這個數區間內,所以:在32位作業系統下,任何型別的指標變數都佔四個位元組!

#include<stdio.h>struct INFO{        int a;        char b;        double c;};int main(){        int *p;        char *p1;        float *p2;        double *p3;        struct INFO *p4;   //struct INFO型別為結構體型別 我們將會在後面的章節中講解        void *p5;        printf("int point size is :%d\n",sizeof(p));        printf("char point size is :%d\n",sizeof(p1));        printf("float point size is :%d\n",sizeof(p2));        printf("double point size is :%d\n",sizeof(p3));        printf("struct point size is :%d\n",sizeof(p4));        printf("void point size is :%d\n",sizeof(p5));        return 0;}#上機執行觀察結果
陣列與指標

前面我們已經知道,透過陣列下標可以確定陣列元素在陣列中的順序和儲存地址。

由於每個陣列元素相當於一個變數,因此指標變數可以指向陣列中的元素,也就是說可以用指標方式訪問陣列中的元素。

對一個指向陣列元素的指標變數的定義和賦值方法,與指標變數相同。例如:

int a[10]; /*定義 a 為包含 10 個整型資料的陣列*/int *p; /*定義 p 為指向整型變數的指標*/p=&a[0]; /*把 a[0]元素的地址賦給指標變數 p*/

C 語言規定,陣列名代表陣列的首地址,也就是第 0 號元素的地址。因此:

p=a; /*等價於 p=&a[0]; */int *p=a; /*等價於 int *p=&a[0]; */

對於指向首地址的指標 p,p+i(或a+i)就是陣列元素 a[i]的地址,*(p+i)( 或*(a+i) )就是 a[i]的值。 如果指標變數 p 已指向陣列中的某一個元素,則 p+1 指向同一陣列中的下一個元素。

引入指標變數後,就可以用以下兩種方法來訪問陣列元素:

(1)下標法:即用 a[i]形式訪問陣列元素,在前面介紹陣列時都是採用這種方法。

(2)指標法:即採用*(a+i)或*(p+i)形式,用間接訪問的方法來訪問陣列元素,其中 a 是陣列名,p 是指向陣列的指標變數,其初值 p=a。

#include<stdio.h>int main(){        int i;        int a[10]={1,2,3,4,5,6,7,8,9,0};        int *p=a;        for(i=0;i<10;i++)        {                printf("P Value:%d   a Value :%d\n",*(p++),*(a+i));        }        printf("\n");        return 0;}

注意輸出的兩種方式,指標可以透過++或--並修改自身值的方式移動,然而陣列名本身值不可以被更改。

char *str = "www.dotcpp.com" ;

這是對字元指標進行初始化。此時,字元指標指向一個字串常量的首地址。 還可以用字元陣列來存放字串,例如:

char string[ ] = "Welcome to dotcpp.com"

在這個語句中,string 是陣列名,代表字元陣列的首地址。

因此可以透過陣列名 string 來訪問字串,字串指標和字串陣列兩種方式都可以訪問字串。

但它們有著本質的區別:字元指標str 是個變數,可以改變str 使它指向不同的字串, 但不能改變 str 所指向的字串常量的值。 而string 是一個數組,可以改變陣列中儲存的內容。應注意字串指標和字串陣列的區別。

#include<stdio.h>int main(){        char *str = "www.dotcpp.com";        char string[]="Welcome to dotcpp.com";        str[0]='C'; //試圖修改str指向的常量區的字串內容        return 0;}

指標是C語言的精髓所在,需要深入理解的同時可以熟練運用指標在不同場合,當然離不開作業的練習,可以把之前的陣列相關的題庫用指標來實現。

關於指標講解的影片部分已上傳,需要的夥伴可自行觀看~

12
  • BSA-TRITC(10mg/ml) TRITC-BSA 牛血清白蛋白改性標記羅丹明
  • Raft一致性演算法