1、計算機內存的每個字節也有編號,這些編號稱為地址,也稱指針。即指針就是地址,地址就是編號,也就是內存中字節的編號。
2、變量位于內存中,如定義變量int a;則變量a要占用內存中的4個字節(在visual c++6.0環境下)。變量a要占用哪4個字節呢?這是由計算機分配的,我們不能左右,而且在不同的計算機上運行程序或在同一計算機的不同時刻運行程序,變量被分配到的位置也不同。然而位置是可以假設的,假設變量a占據了內存中編號為1000~1003的4個字節,則這4個字節就被標記名稱為“a”。用變量a保存一個整數,就是用這4個字節保存一個整數。例如執行語句a==1;則1就被保存到這4個字節中。
3、如果財務處位于辦公樓的305,我們稱財務處的地址是305,如果財務處比較大,占用了305-307三間房間,習慣上我們仍稱財務處的地址為305,即取第一間房間號為地址。對于變量a,它占用了編號為1000-1003的4個字節,我們說變量a的地址為1000,也取它的第一個字節的編號作為變量的地址。注意變量a的地址為1000,變量a并不一定只占用編號為1000的這一個字節。(注意這里變量的地址都是假設的,實際運行程序時其地址不一定是1000、2000.例如變量a的實際地址可能是2031132,變量b的實際地址可能是3209356,而且一般以十六進制表示,分別為0x001efe1c、0x0030f88c)
4、變量的地址和變量的值
變量的地址:變量位于存儲空間的“門牌號”,在整個程序運行期間,地址永久不變。
變量的值:變量空間中所保存的數據內容,在程序運行期間,變量的值是可以變化的。
5、訪問變量有兩種方式:(1)通過變量名(2)通過變量的地址。
訪問變量:就是存取變量的值。
6、在程序中地址也需要變量來保存,然而地址不能被保存在普通變量中,C語言提供有一種特殊的專有變量專門用來保存地址,這種變量稱為指針變量,指針變量也可簡稱為指針。“指針”準確含義有兩個意思:一個是地址,二是指針變量。
7、定義指針變量
int ?*p;
注意:變量名是p,不是*p。變量p的類型是int *,不是int。
可以通過如下語句將a的地址保存到p中:p=&a;
其中&表示取地址,我們在scanf語句中也使用過這個符號。&a表示變量a的地址,p=&a;則便是將a的地址賦值給指針變量p。
下面的做法是錯誤的:
int x;
x=&a;
x不是指針變量,不能保存地址。盡管內存中的字節編號是“整數”的,也不能用一個int型的變量來保存這種字節編號。
下面的做法也是錯誤的:
p=1;
因為p不能保存普通整數。
注意:1、由于變量a和變量x的定義語句分別是int a;int x;都沒有*號,所以a、x都是普通變量,他們只能保存普通數據,不能保存地址。
2、由于變量p的定義語句是int *p;有*號,所以p是指針變量,他只能保存地址,不能保存普通數據。
3、指針變量也是變量,普通變量的特性指針變量同樣具有。指針變量的空間也位于內存中,規定指針變量一律都占用4個字節。指針變量占用哪4個字節呢?它在內存中的位置也是由計算機分配的。但我們仍然可為其假設一個位置。假設指針變量p占據3000-3003的4個字節,這樣也可以說,指針變量p的地址是3000.3000-3003的4個字節將用于保存一個地址,而不是用來保存 普通數據的。
5、指針變量p保存了普通變量a的地址,就是“對準了”普通變量a,因為將可通過p中保存的這個地址來訪問變量a(就是存取變量a)。我們稱:指針變量p指向了變量a或稱p是指向變量a的指針變量。由于指針變量還可以簡稱為指針,后一句還可稱為“p是指向變量a的指針”。
6、在一條定義語句中可以同時定義多個指針變量,也可以同時電議普通變量與指針變量,比如:
double *m, *n;
int ?*x,y, ?*z;
7、int ?*p;
變量p的類型是int ?*類型的。“int ?*”類型是什么含義呢?它表示指針變量p所指向的數據的類型是int型,也就是說將來p要保存一個地址,但這個地址有講究,必須是一個int型數據的地址才能被保存。
8、在定義指針變量時,*號之前的類型如int ?*中的int是表示該指針變量將保存何種類型數據的地址,換句話就是說指針變量所能指向的數據的類型,該類型成為指針變量的基類型。指針變量要保存的地址必須是 基類型這種類型數據的地址,指針變量只能指向同基類型的數據。
void基類型指針。基類型表示任意類型。
void ?*pt; ? pt可以保存任意類型數據的地址,而無論數據是什么類型的。
9、為指針變量賦值。為指針變量賦值,兩種方式:通過賦值語句的方式,或在變量定義時賦初值。
(1)通過賦值語句為指針變量賦值。
int ? a=1;
int ? ? *p;
p=&a;
注意:同普通變量類似,在為指針變量賦值之前,指針變量的值也是不確定的,也是隨機數。它里面是個隨機地址。
建議在定義指針變量的同時為其賦初值。
(2)定義指針變量時賦初值(定義時初始化)
int ?*p=&a;
(3)指針變量之間彼此互相賦值。所賦的值是其中保存的地址。賦值要求兩個指針變量基類型必須相同。
int ?*p=&a;
int ? *q;
q=p;/*則q、p均保存了變量a的地址,q、p均指向了變量a*/
(4)不允許把一個“數”當做地址直接賦值給指針變量。
int ?*p;p=1000;/*錯誤,即使我們知道某個變量的地址是1000也不能這么干*/
特殊的,允許把數值0直接賦值給指針變量。p=0;(系統規定,如果一個指針變量里保存的地址為0,則說明這個指針變量不指向任何內容,叫做空指針)。
系統在stdio.h頭文件中定義有符號常量NULL(#define NULL 0),因此也可寫為:
p=NULL;/*正確,NULL是0的代替符號,仍是p=0的意思,注意NULL四個字母必須全部大寫*/
注意:指針變量未賦值和賦0值是不同的,指針變量未賦值時,其保存的地址是隨機地址,是不能使用的。而降指針變量賦0值,其保存的地址是0,是確定的,它不指向任何內容。
在定義指針變量時,如果不能確定它所指向的位置,可以先將其初始化為0或NULL,以免指針變量的隨機指向。例如:int ? *p=0;
10、指針運算倆兄弟——兩個運算符
(1)&取地址運算符。獲取變量的地址,寫作&變量名。&運算符既可以取普通變量的地址,也可以取指針變量的地址。&p得到的地址是3000,&a得到的地址是1000.
(2)*指針運算符(或稱間接訪問運算符,只用于指針變量)。獲取或改寫以p為地址的內存單元的內容,寫做*指針變量名。它就是“按圖索驥”,按照p中所保存的地址,找到數據的意思。
舉例:
int ?*p;
int a=1;
p=&a;
printf("%d",*p);//輸出1
printf(“%d”,p);//輸出p本身的值即,輸出a的地址。229416
如果已經定義int b;還可以執行:
b=*p;
以上語句是將a的內容1賦值給b。但如寫為b=p;是錯誤的,因為它是把p中所保存的地址本身賦值給b,而變量b是不能保存地址的。
*p=2;
以上語句是將2送入p所指向的變量中,即a被賦值為2,它等價于語句a=2;實際上*p等價于a,用*p或用a都能存取a這個變量;前者是通過地址的“門牌號”訪問變量,后者是通過變量名訪問變量。
11、&和*都是單目運算符,結合方向“自右向左”。&和*互為逆運算,即一個&和一個*可以相互抵消,如果有p=&a,則:&*p<=>&a ? ?*&*&*&*p<=>*p<=>a
12、定義指針變量時的的*和執行語句中運算符的*是完全不同的,它們是兩種符號。
(1)在變量定義時寫*就是指針變量的標志(前有int、double等類型說明符),如int ?*p;的*,它沒有任何“取數據”或“改數據”的含義。
(2)在執行語句中寫*(前沒有int、double等類型說明符)才是“取數據”或“改數據”的含義。
13、&:僅右邊有一個量時取地址。
14、變量地址是計算機分配的,在不同的計算機上或在不同時刻運行程序都可能會有所不同。