指標被稱為是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:1 int Address:0xbfb949c8,Value:2 int Address:0xbfb949cc,Value:3 int Address:0xbfb949d0,Value:4 int Address:0xbfb949d4,Value:5 int Address:0xbfb949d8,Value:6 int Address:0xbfb949dc,Value:7 int Address:0xbfb949e0,Value:8 int Address:0xbfb949e4,Value:9 int Address:0xbfb949e8,Value:0 char Address:0xbfb949f2,Value :c char Address:0xbfb949f3,Value :l char Address:0xbfb949f4,Value :a char Address:0xbfb949f5,Value :n char Address:0xbfb949f6,Value :g char Address:0xbfb949f7,Value :u char Address:0xbfb949f8,Value :a char Address:0xbfb949f9,Value :g char Address:0xbfb949fa,Value :e char 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語言的精髓所在,需要深入理解的同時可以熟練運用指標在不同場合,當然離不開作業的練習,可以把之前的陣列相關的題庫用指標來實作,
期末了,為大家提供C語言基礎視頻資料,節約備考時間,不用去網上找資源,還有考試真題可以免費領取噢,需要的伙伴可以加群一起學習:1151395975

轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/240323.html
標籤:C
