C語言的指標

2021-09-18 04:54:33 字數 4848 閱讀 1852

目錄

一、位址(指標)

二、指標變數

指標變數的運算

指標和陣列名

指標作為函式形參

三、指標型別

常見指標

陣列指標

二級指標

二維陣列指標

指標陣列

指標函式

函式指標

計算機中所有的資料都必須放在記憶體中,為了正確地訪問這些資料,必須為每個位元組都編上號碼,每個位元組的編號是唯一的,根據編號可以準確地找到某個位元組。我們將記憶體中位元組的編號稱為位址(address)或指標(pointer)。

資料和**都以二進位制的形式儲存在記憶體中,計算機無法從格式上區分某塊記憶體到底儲存的是資料還是**。當程式被載入到記憶體後,作業系統會給不同的記憶體塊指定不同的許可權,擁有讀取和執行許可權的記憶體塊就是**,而擁有讀取和寫入許可權(也可能只有讀取許可權)的記憶體塊就是資料。

cpu 只能通過位址來取得記憶體中的**和資料,cpu 訪問記憶體時需要的是位址而不是變數名和函式名,變數名和函式名只是位址的一種助記符,當原始檔被編譯和鏈結成可執行程式後,它們都會被替換成位址。編譯和鏈結過程的一項重要任務就是找到這些名稱所對應的位址。

雖然變數名、函式名、字串名和陣列名在本質上是一樣的,它們都是位址的助記符,但在編寫**的過程中,可認為變數名表示的是資料本身,而函式名、字串名和陣列名表示的是**塊或資料塊的首位址。

用來存放指標的變數稱為指標變數。指標變數的值就是某份資料的位址。

指標變數 p 的值為等於變數 c 的位址,則稱 p 指向了 c,或者說 p 是指向變數 c 的指標。

定義指標:

int *p = &c;
獲取指標指向的資料:

*pointer;
*  的作用:

定義指標變數時加上 * 表明這是乙個指標變數,以和普通變數區分開;

使用指標變數時在前面加*表示獲取指標指向的資料,*為指標運算子,用來取得某個位址上的資料;

定義指標變數時必須帶*,給指標變數賦值時不能帶*。

cpu 讀寫資料必須要知道資料在記憶體中的位址,普通變數和指標變數都是位址的助記符,使用變數名是通過位址直接獲取資料,使用指標是先通過位址獲取變數的位址,再通過改位址獲取資料。

使用指標變數之前一定要初始化,否則就不能確定指標指向**,如果它指向的記憶體沒有使用許可權,程式就崩潰了。對於暫時沒有指向的指標,建議賦值null,注意區分大小寫。

c語言沒有規定 null 的指向,只是大部分標準庫約定成俗地將 null 指向 0,所以不要將 null 和 0 等同起來。

指標變數儲存的是位址,本質上是乙個整數,可以進行加法、減法、比較運算,但不能對指標變數進行乘法、除法、取餘等其他運算,除了會發生語法錯誤,也沒有實際的含義。

對於指向普通變數的指標,往往不進行加減運算,這樣做沒有意義,因為不知道它後面指向的是什麼資料;對於指向陣列的指標,陣列中的所有元素在記憶體中是連續排列的,進行加減運算就可以表示上乙個或下乙個元素

c語言標準規定,陣列下標與指標的偏移量相同,也就是對陣列下標的引用總是可以寫成「乙個指向陣列的起始位址的指標加上偏移量」。

對陣列的引用 a[i] 在編譯時總是被編譯器改寫成*(a+i)的形式。

取下標操作符[ ]是建立在指標的基礎上,它的作用是使乙個指標和乙個整數相加,產生出乙個新的指標,然後從這個新指標(新位址)上取得資料。

c語言標準規定,當陣列名作為陣列定義的識別符號(即定義或宣告陣列時)、sizeof 或 & 的運算元時,它才表示整個陣列本身,在其他的表示式中,陣列名會被轉換為指向第 0 個元素的指標(位址)。

可將陣列名認為是乙個指標,但陣列名和陣列首位址並不總是等價。

c語言標準規定,作為「型別的陣列」的形參應該調整為「型別的指標」。在函式形參定義這個特殊情況下,編譯器必須把陣列形式改寫成指向陣列第 0 個元素的指標形式。編譯器只向函式傳遞陣列的位址,而不是整個陣列的拷貝。

向函式傳遞陣列時,可以把函式引數定義為陣列形式(可以指定長度也可以不指定長度),也可以定義為指標。不管哪種形式,在函式內部都要作為指標變數對待。

在函式內部,arr 會被轉換成乙個指標變數,編譯器為 arr 分配 4 個位元組的記憶體,用 sizeof(arr) 求得的是指標變數的長度,而不是陣列長度。要想在函式內部獲得陣列長度必須額外增加乙個引數,在呼叫函式之前求得陣列長度。

用指標變數作函式引數可以將函式外部的位址傳遞到函式內部,使得在函式內部可以操作函式外部的資料,並且這些資料不會隨著函式的結束而被銷毀。

void function(int &a):

引用就是指標,兩者沒有區別。我們可以把引用想象成乙個不需要"*"就可以訪問變數的指標

int &b = i;//這裡b是乙個引用,它是變數i的引用

呼叫:int x = 200; function(x);

名稱

定義含  義

陣列指標

int *p;

p 可以指向 int 型別的資料,也可以指向類似 int arr[n] 的陣列。

二級指標

int **p;

p 為二級指標,指向 int * 型別的資料。

指標陣列

int *p[n];

p 為指標陣列。每個元素都是指標。

二維陣列指標

int (*p)[n];

p 為二維陣列指標。

指標函式

int *p();

p 是乙個函式,它的返回值型別為 int *。

函式指標

int (*p)();

p 是乙個函式指標,指向原型為 int func() 的函式。

c語言標準規定,對於乙個符號的定義,編譯器總是從它的名字開始讀取,然後按照優先順序順序依次解析。

陣列中運算子的優先順序:

定義中被括號( )括起來的那部分。

字尾操作符:括號( )表示這是乙個函式,方括號[ ]表示這是乙個陣列

字首操作符:星號*表示「指向***的指標」

如果乙個指標指向了陣列,我們就稱它為陣列指標(array pointer)。

定義:

int *p = arr;

或int *p = &arr[0];

arr、p、&arr[0] 這三種寫法都是等價的,它們都指向陣列第 0 個元素,或者說指向陣列的開頭。

兩種訪問陣列元素的方案,一種是使用下標,另外一種是使用指標。

自增運算子的優先順序高於指標運算子,*p++ 應該理解為 *(p++),該語句不能寫為 *arr++,因為 arr 是常量,而 arr++ 會改變它的值,從而產生錯誤。

如果乙個指標指向的是另外乙個指標,我們就稱它為二級指標,或者指向指標的指標。

將這種關係轉換為c語言**:

int a =100;

int *p1 = &a;

int **p2 = &p1;

指標變數也是一種變數,也會占用儲存空間,也可以使用&獲取它的位址。c語言不限制指標的級數,每增加一級指標,在定義指標變數時就得增加乙個星號*。

實際開發中會經常使用一級指標和二級指標,幾乎用不到高階指標。

定義乙個指向 a 的指標變數 p:

int (*p)[n] = a;
從 p 開始理解,( ) 的優先順序最高,編譯器先解析(*p),p 首先是乙個指標,剩下的int [n]是 p3 指向的資料的型別,它是乙個擁有 n 個元素的一維陣列。從整體上講,p 是乙個指向擁有 n 個 int 元素陣列的指標,也即二維陣列指標。

為了能夠通過指標來遍歷陣列元素,在定義陣列指標時需要進行降維處理,例如三維陣列指標實際指向的資料型別是二維陣列,二維陣列指標實際指向的資料型別是一維陣列,一維陣列指標實際指向的是乙個基本型別;在表示式中,陣列名也會進行同樣的轉換(下降一維)。

*(p+i)表示整個第 i 行的資料,*(*(p+i)+j)表示第 i 行第 j 個元素的值。

*(p+1)表示整個第 1 行資料,不是第 1 行中的第 0 個元素,放在表示式中會被轉換為第 1 行資料的首位址,也就是第 1 行第 0 個元素的位址,因為使用整行資料沒有實際的含義,編譯器遇到這種情況都會轉換為指向該行第 0 個元素的指標。就像一維陣列的名字,在定義時或者和 sizeof、& 一起使用時才表示整個陣列,出現在表示式中就會被轉換為指向陣列第 0 個元素的指標。

定義:

int *p[n];
從 p 開始理解,[ ] 的優先順序高於 *,所以編譯器先解析p[n],p 首先是乙個擁有 n 個元素的陣列,然後再解析int *,它用來說明陣列元素的型別。從整體上講,p 是乙個擁有 n 個 int * 元素的陣列,即指標陣列。

c語言允許函式的返回值是乙個指標(位址),我們將這樣的函式稱為指標函式。

char *strlong(char *str1, char *str2)
int (*p)(int, int);
從 p 開始理解,( ) 的優先順序最高,編譯器先解析(*p),p 首先是乙個指標,它後邊的 ( ) 說明 p 指向的是乙個函式,括號中的int, int是引數列表,開頭的int用來說明函式的返回值型別。整體來看,p4 是乙個指向原型為int func(int, int);的函式的指標。

乙個函式總是占用一段連續的記憶體區域,函式名在表示式中有時也會被轉換為該函式所在記憶體區域的首位址,這和陣列名非常類似。我們可以把函式的這個首位址(或稱入口位址)賦予乙個指標變數,使指標變數指向函式所在的記憶體區域,然後通過指標變數就可以找到並呼叫該函式,這種指標就是函式指標。

C語言的指標

如果乙個指標變數存放的又是另乙個指標變數的位址,則稱這個指標變數為指向指標的指標變數。在前面已經介紹過,通過指標訪問變數稱為間接訪問。由於指標變數直接指向變數,所以稱為 單級間址 而如果通過指向指標的指標變數來訪問變數則構成 二級間址 從下圖可以看到,name是乙個指標陣列,它的每乙個元素是乙個指標...

C語言的指標

1 num 使num對應的記憶體空間的值加一 0x1000 0x1004 2 p p所指向的記憶體空間的值加一 3 p p對應的記憶體空間的值加一 0x1000 0x1001 指向的記憶體空間 根據指標變數對應的記憶體空間儲存的位址,再找到該位址所對應的記憶體空間 int p 整型指標的指標的指標變...

C語言的指標

const與指標 遵循靠近誰就修飾誰的原則 1.const int p 靠近所以修飾指標所指向的值,因而指標指向的值不可以修改。但是原來變數可以修改,只是不能用 p修改而已 2.int const p 和上面一樣。3.int const p 靠近變數本身,所以指標位址不能修改。4.const int...