C Note(NO.5)

存儲器中的一個字節稱爲一個內存單元,內存單元的編號也叫做地址,據內存單元的編號或地址就可以找到所需的內存單元,所以通常也把這個地址稱爲指針。
在C語言中,允許用一個變量來存放指針,這種變量稱爲指針變量。因此,一個指針變量的值就是某個內存單元的地址或稱爲某內存單元的指針。
指針”是指地址,是常量,“指針變量”是指取值爲地址的變量。
凡是出現數組,函數的地方都可以用一個指針變量來表示,只要該指針變量中賦予數組或函數的首地址即可。這樣做,將會使程序的概念十分清楚,程序本身也精練,高效。

變量的指針就是變量的地址。存放變量地址的變量是指針變量。即在C語言中,允許用一個變量來存放指針,這種變量稱爲指針變量。因此,一個指針變量的值就是某個變量的地址或稱爲某變量的指針。在程序中用“ *”符號表示“指向”。

對指針變量的定義包括三個內容:
(1) 指針類型說明,即定義變量爲一個指針變量;
(2) 指針變量名;
(3) 變量值(指針)所指向的變量的數據類型。

其一般形式爲:類型說明符 *變量名;其中, *表示這是一個指針變量,變量名即爲定義的指針變量名,類型說明符表示本指針變量所指向的變量的數據類型。例如: int *p1;表示 p1 是一個指針變量,它的值是某個整型變量的地址。一個指針變量只能指向同類型的變量。

兩個有關的運算符:
1) &:取地址運算符。
2) *:指針運算符(或稱“間接訪問” 運算符)。
int a;
int *p=&a;
1. 指針運算符
 1) 取地址運算符&:取地址運算符&是單目運算符,其結合性爲自右至左,其功能是取變量的地址。
 2) 取內容運算符*:取內容運算符*是單目運算符,其結合性爲自右至左,用來表示指針變量所指的變量。在*運算符之後跟的  變量必須是指針變量。
需要注意的是指針運算符*和指針變量說明中的指針說明符*不是一回事。在指針變量說明中, “*”是類型說明符,表示其後的變量是指針類型。而表達式中出現的“*”則是一個運算符用以表示指針變量所指的變量。
 2. 指針變量的運算

a. 把數組的首地址賦予指向數組的指針變量。
例如:
int a[5],*pa;
pa=a;
(數組名錶示數組的首地址,故可賦予指向數組的指針變量 pa)
也可寫爲:
pa=&a[0]; /*數組第一個元素的地址也是整個數組的首地址, 也可賦予 pa*/
當然也可採取初始化賦值的方法:
int a[5],*pa=a;
b. 把字符串的首地址賦予指向字符類型的指針變量。
例如:
char *pc;
pc="C Language";
或用初始化賦值的方法寫爲:
char *pc="C Language";
這裏應說明的是並不是把整個字符串裝入指針變量,而是把存放該字符串的字符數組的首地址裝入
指針變量。在後面還將詳細介紹。
c. 把函數的入口地址賦予指向函數的指針變量。
例如:
int (*pf)();
pf=f; /*f 爲函數名*/
3. 兩個指針變量之間的運算:只有指向同一數組的兩個指針變量之間才能進行運算,否則運算毫無意義。
① 兩指針變量相減:兩指針變量相減所得之差是兩個指針所指數組元素之間相差的元素個數。實際上
第 147 頁
是兩個指針值(地址)相減之差再除以該數組元素的長度(字節數)。

② 兩指針變量進行關係運算:指向同一數組的兩指針變量進行關係運算可表示它們所指數組元素之間
的關係。
 

整型二維數組 a[3][4]

a 是二維數組名, a 代表整個二維數組的首地址,也是二維數組 0 行的首地址,a[0]是第一個一維數組的數組名和首地址,*(a+0)或*a 是與 a[0]等效的, 它表示一維數組 a[0]0 號元素的首地址,&a[0][0]是二維數組 a 的 0 行 0列元素首地址,因此, a, a[0], *(a+0), *a, &a[0][0]是相等的。同理, a+1 是二維數組 1 行的首地址,等於 1008。 a[1]是第二個一維數組的數組名和首地址,&a[1][0]是二維數組 a 的 1 行 0 列元素地址,也是 1008。因此a+1,a[1],*(a+1),&a[1][0]是等同的,由此可得出: a+i, a[i], *(a+i), &a[i][0]是等同的。此外, &a[i]和 a[i]也是等同的,a[i], &a[i], *(a+i)和 a+i 也都是等同的。由 a[i]=*(a+i)得 a[i]+j=*(a+i)+j。由於*(a+i)+j 是二維數組 a 的 i 行 j 列元素的首地址,所以,該元素的值等於*(*(a+i)+j)。

 

二維數組指針變量說明的一般形式爲:
類型說明符 (*指針變量名)[長度]其中“類型說明符”爲所指數組的數據類型。“ *”表示其後的變量是指針類型。 “長度”表示
二維數組分解爲多個一維數組時,一維數組的長度,也就是二維數組的列數。應注意“(*指針變量名)”兩邊的括號不可少,
如:int (*p)[4]

1. 字符串指針變量本身是一個變量,用於存放字符串的首地址。而字符串本身是存放在以該首地址爲首的一塊連續的內存空間中並以‘ \0’作爲串的結束。字符數組是由於若干個數組元素組成的,它可用來存放整個字符串。
2. 對字符串指針方式
char *ps="C Language";
可以寫爲:
char *ps;
ps="C Language";
而對數組方式:
static char st[]={"C Language"};
不能寫爲:
    char st[20];
     st={"C Language"};
  而只能對字符數組的各元素逐個賦值。

在C語言中,一個函數總是佔用一段連續的內存區,而函數名就是該函數所佔內存區的首地址。我們可以把函數的這個首地址(或稱入口地址)賦予一個指針變量,使該指針變量指向該函數。然後通過指針變量就可以找到並調用這個函數。我們把這種指向函數的指針變量稱爲“函數指針變量”。
函數指針變量定義的一般形式爲:
類型說明符 (*指針變量名)();
其中“類型說明符”表示被指函數的返回值的類型。“ (* 指針變量名)”表示“*”後面的變量是定義的指針變量。最後的空括號表示指針變量所指的是一個函數
 例如:int (*pf)();表示 pf 是一個指向函數入口的指針變量,該函數的返回值(函數值)是整型。

 

在C語言中允許一個函數的返
回值是一個指針(即地址),這種返回指針值的函數稱爲指針型函數。
定義指針型函數的一般形式爲:
類型說明符 *函數名(形參表)
{
…… /*函數體*/
}
其中函數名之前加了“ *”號表明這是一個指針型函數,即返回值是一個指針。類型說明符
表示了返回的指針值所指向的數據類型。
如:
int *ap(int x,int y)
{
...... /*函數體*/
}
表示 ap 是一個返回指針值的指針型函數,它返回的指針指向一個整型變量。
int (*p)()是一個變量說明,說明 p 是一個指向函數入口的指針變量,該函數的返回值是整型量, (*p)的兩邊的括號不能少。
int *p()則不是變量說明而是函數說明,說明 p 是一個指針型函數,其返回值是一個指向整型量的指針, *p 兩邊沒有括號。作爲函數說明,在括號內最好寫入形式參數,這樣便於與變量說明區別。對於指針型函數定義, int *p()只是函數頭部分,一般還應該有函數體部分。

一個數組的元素值爲指針則是指針數組。 指針數組是一組有序的指針的集合。 指針數組的所有元素都必須是具有相同存儲類型和指向相同數據類型的指針變量。指針數組說明的一般形式爲:
   類型說明符 *數組名[數組長度]

其中類型說明符爲指針值所指向的變量的類型。
 例如:
int *pa[3]
表示 pa 是一個指針數組,它有三個數組元素,每個元素值都是一個指針,指向整型變量。

 

二維數組指針變量是單個的變量,其一般形式中"(*指針變量名)"兩邊的括號不可少。而指針數組類型表示的是多個指針(一組有序指針)在一般形式中"*指針數組名"兩邊不能有括號。
例如:
        int (*p)[3];
表示一個指向二維數組的指針變量。該二維數組的列數爲 3 或分解爲一維數組的長度爲3。
        int *p[3]
表示 p 是一個指針數組,有三個下標變量 p[0], p[1], p[2]均爲指針變量。 如果一個指針變量存放的又是另一個指針變量的地址,則稱這個指針變量爲指向指針的指針變量。通過指向指針的指針變量來訪問變量則構成“二級間址”。
 

char **p;
p 前面有兩個*號,相當於*(*p)。顯然*p 是指針變量的定義形式,如果沒有最前面的*,那就是定義了一個指向字符數據的指針變量。現在它前面又有一個*號,表示指針變量 p 是指向一個字符指針型變量的。 *p 就是 p 所指向的另一個指針變量。

C語言規定 main 函數的參數只能有兩個,習慣上這兩個參數寫爲 argc 和 argv。因此, main 函數的函數頭可寫爲:
main (argc,argv)
C語言還規定 argc(第一個形參)必須是整型變量,argv( 第二個形參)必須是指向字符串的指針數組。加上形參說明後, main 函數的函數頭應寫爲:
main (int argc,char *argv[])
由於 main 函數不能被其它函數調用,因此不可能在程序內部取得實際值。
 

 

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章