1. 程式人生 > >近期對C/C++裡指標的一些認識

近期對C/C++裡指標的一些認識

C語言系最大的特點就是指標

在C語言系裡,指標實際上就是一個地址。

int num = 0;
int *ip =  #
printf("pointer: 0x%.8lx address: 0x%.8lx",ip, &num);

這裡打印出來的pointeraddress將會是一樣的值,如果在64位機器上執行,可以將精度調成更高的。

指標的運算

我聽說以前C語言沒有泛型指標,也就是現在的void,當時用char*可以表示指向任意一個型別的指標。
為什麼可以這樣呢?以下面的程式碼為例

int num = 0;
int *ip = #
char *cp = (char
*)#

那麼cpip的值實際上是一樣的,但是他們又不一樣的地方:

  • 這裡有一點需要說明的是下面敘述中&num+4在程式裡實際上是和指標運算一樣的,我這裡當做地址加減,純粹的地址加減。
  1. ip進行運算,比如ip++將會得到&num + sizeof(int),而對cp進行運算,同樣的,cp++,得到的是&num + sizeof(char),也就是指標運算不一樣
  2. &ip[1]&cp[1],也是不一樣的,這個就和第一點類似
    也就是最主要的就是對地址的解釋不一樣(我是這麼理解的),那麼在返回char*後,可以使用casting,強制轉換型別,既然返回的地址是一樣的,那麼我把這個地址按照我想要的方式去解釋,然後再把地址裡的內容取出來就是我想要的東西。

更直觀的看看下面的程式碼

int *ip = (int *)malloc(2*sizeof(int));
char *p = (char*)ip;
*ip = 1;
*((int *)p+1) = 2;
printf("ip[0]:%d ip[1]%d",ip[0],ip[1]);

將會輸出一下結果ip[0]:1 ip[1]2,程式碼中把ip地址首先按照char* 解釋,賦值給了p,然後在第四行,又將p地址按照int*來解釋,那麼p+1自然就到了&ip[0]+4的位置。

指標和陣列的聯絡

稍微瞭解一點C語言的人都知道,陣列和指標是不分家的,陣列名就是一個指標,也是陣列的起始地址,一個數組既可以通過下標訪問,又可以通過指標訪問。在程式實際執行過程中,指標訪問是要快一點的,下標訪問每次迭代出下標後,程式會根據下標運算出地址,實際上做了重複運算,這裡不重點敘述。
一個數組array[5]

,有五個元素,首地址是array,也是&array[0],array[i],*array+i,*&array[0]+i都是等價的。

多維陣列

看看下面的程式碼:

int array[4][5];
int *p = (array+1);
int *end = &array[3][4];
while(p != end){
	*p = 1;
	p++;
}

要想看懂這段程式碼,唯一的關鍵就是理解

int *p = (array + 1);

在幹什麼,實際上這句程式碼和下面這句程式碼是等效的

int *p = array[1];

array 是一個4元素陣列,每個元素由5 int陣列構成,所以array[1]是一個5 int 陣列的名稱,也就是首地址,和array+1, 相當於&array[0]+sizeof(int[5]),所以上面的程式碼就做了一件事,遍歷了array[1] [0]之後的所有元素,賦值為1。

總結

陣列名稱是首地址,也是指標,對它進行運算就是相當於首地址加上其中元素長度。

指標和陣列還有函式的優先順序

指標的優先順序比陣列[]還有函式()都低,因此在宣告一個函式指標時必須這樣:

int (*p)(int arg);

這裡p是一個指標,指向一個函式,函式接收一個int的引數,返回一個int 值
再來看看指標和陣列的優先順序

int *p[5];
int (*p)[5];

第一行大家都比較熟悉,是一個數組,有5個int*的元素
第二行可能就比較陌生了,p是一個指標,指向一個擁有5個int元素的陣列

陣列和指標的區別

  1. 最明顯的區別應該就在size上了,比如下面的程式碼
char arr[5];
char *p;

第一行聲明瞭一個5元素的字元陣列,sizeof(arr)將會返回5,而sizeof(p)將會返回8(在64位機器上)
這裡又要提到一個很不常見的宣告:

char arr[0];

聲明瞭一個0元素的陣列,那麼sizeof(arr)是多少呢,如果你實驗一下就會發現,居然是0,這個可以當做指標來用的居然不佔空間,也是很奇特的。

以上就是最近學習碰到的一些知識,記錄下來以免忘記,順便和大家分享,如有錯誤,還請指正,大家共同進步~~