此文爲指針系列第二篇:html
C語言精要總結-指針系列(二)函數
前面提到過指針的解引用運算,除此以外,指針還能進行部分算數運算、關係運算工具
指針能進行的有意義的算術運算包括加減法運算,但不包括乘除運算。而且運算存在諸多限制。ui
加法運算spa
指針加法運算只適合指針與整數,不能用在指針與指針。3d
指針加上或者減去一個整數n,是存儲的地址值加上或者減去n*指針指向類型的空間大小。也就是指針
結果指針 = 指針 ± n * 指針指向類型空間大小。code
例如int類型的整數指針+1,運算結果依然是一個整型指針,其存儲的地址值爲原指針值+1*4,這是由於整型變量佔用4個字節的空間。這個計算結果,剛好在當前指針指向基礎上,向下偏移指向下一個相同類型的空間。以下圖htm
指針與整數的加減法通常用在迭代連續的內存空間-數組,若是運算獲得的指針指向第一個元素以前或者最後一個元素以後,可能會產生非法讀寫內存中斷,就像引用一個未初始化的指針同樣不可預知。
指針除了能夠與整數作加減運算,連個指針之間還能夠作減法運算(不能作加法運算)且必須是同類型的指針。運算結果爲兩個指針指向地址之間,能夠存放多少此類型的變量數(或其相反數),類型爲ptrdiif_t類型(一種有符號整數類型)。
1 int * p1 = (int *) 0x100; 2 int * p2 = (int *) 0x10c; 3 printf("p2-p1 : %d\n",p1 - p2); // -3
如上程序將輸出-3,也如上圖所示,這3個空間存放着 十、80、6三個整型變量。
指針與指針相減,通常也用在連續地址空間-數組中。此時兩個指針相減跟下標索引相減是等價的。
1 int arr[5] ; 2 printf("%d\n",&arr[4] - &arr[0] == 4 - 0); // 1
常量指針表示經過此指針,不能修改其指向的內存區域的內容,指針自己的值是能夠修改成指向另外一個變量,雖然能夠修改指向另外一個變量,可是依然不容許修改指向變量裏的內容。常量指針通常用在函數一些函數參數中,以只讀的方式傳遞函數參數。這裏說明一點C語言除了宏定義常量和枚舉以外,是不能定義普一般量的,只可用const定義只讀變量,而常量指針指向的是就是一個只讀變量。只讀變量是不能修改的變量。
1 const int readOnlyVar = 10; 2 int * pROVar = (int *) & readOnlyVar; 3 * pROVar = 11; 4 printf("%d\n",readOnlyVar);
而指針常量表示指針自己的內容不可變(指向不可變),所以,定義指針常量時必須同時初始化一個地址值。
定義指針常量和定義常量指針的方式區別在於const關鍵字的位置
int const * p1 ; const int * p2 ; int * const p3 = NULL; const int * const p4 = NULL;
以*號爲界限,看cosnt修飾的是誰,若是修飾的是類型關鍵字,表示指向常量類型——常量指針,若是修飾的是指針標識符,表示指針常量。顯然p一、p2是常量指針,p3是指針常量,p4既是常量指針,又是指針常量。
指針數組指元素由指針組成的數組,通常用在存儲字符串組,例以下面的程序
1 char * options[5] = { 2 "--list", 3 "--prefix", 4 "--with" 5 }; 6 for (i = 0 ; i < 5 ;i ++) 7 { 8 if (NULL != options[i]){ 9 printf("%s\n",options[i]); 10 } 11 }
此時指針數組前三個成員指向靜態區的三個字符串常量,然後兩個指針被默認初始化爲0(NULL)
C語言中出現的字符串字面量,實際是存儲在靜態數據區的字符串常量。當一個字符串出如今C語言表達式中,其實際值是一個指針常量。以下面聲明一個指針常量的代碼
char * str = "hello";
能夠用另外一段代碼來描述,即先在某處爲字符串分配空間,記錄指向第一個字符的一個指針常量,並將字符拷貝進去。代碼以下
char * const strBuff = (char * ) malloc (6); strcpy(strBuff,"hello"); char * str = strBuff; free(strBuff);
既然明確字符串常量在代碼中實際是一個指針常量,所以其也能夠參與運算。代碼以下
printf("%c\n",* "hello"); // h printf("%s\n", "hello" + 1);// ello
常量指針「hello」+1後獲得一個新的指針,按指針運算的規則將指向下一個e,因此以字符串形式輸出ello
除此以外指針輸在還用在處理許多多維數組的地方,這在後續的章節中會提到。
常量指針數組表示元素都指向常量的數組。定義方式以下
1 const char * options[5] = { 2 "--list", 3 "--prefix", 4 "--with" 5 };
固然,這裏的例子,const加與不加沒太大區別,由於即使不加const關鍵字,options中的每個元素依然是指向一個字符串常量,是不能修改的。例如要將「--list」中的第2個‘-’換成'+'號,下面的代碼是行不通的,方法只有讓指針指向一個全新的字符串常量(由於是常量指針,因此指針自己的內容能夠修改)
* (options[0] + 1) = '+';
加上const的好處是,讓編譯器或者IDE工具在運行以前便告知你此類代碼存在的問題。關於字符串常量,下面的異常代碼可能更易懂一些
char * str = "hello"; *(str + 3) = 'w';
指針常量數組表示每一個指針元素都是不可修改的(指向固定了),可是其指向內容,視狀況是能夠修改的。
1 char * const options[5] = { 2 "--list", 3 "--prefix", 4 "--with" 5 };
固然,由於字符串常量的緣故,上面的代碼定義了一個指針元素、指針元素指向區域內都不可變的指針數組。例如,像下面的代碼都是非法的
1 options[0] = tmpStr; // 修改指針指向新的字符串常量 2 *(options[0]) = '+'; // 修改第一個元素指向區域的內容
下一系列將用一兩個複雜的案例詳細講解指針與數組的關係。