解析C語言編程中指針賦值的實例
從const int i 説起
你知道我們聲明一個變量時象這樣int i ;這個i是可能在它處重新變賦值的。如下:
int i = 0;/* . . . */i = 20; /*這裏重新賦值了*/
不過有一天我的程序可能需要這樣一個變量(暫且稱它變量),在聲明時就賦一個初始值。之後我的程序在其它任何處都不會再去重新對它賦值。那我又應該怎麼辦呢?用const 。
/* . . . */const int ic =20;/* . . . */ic = 40; /*這樣是不可以的,編譯時是無法通過,因為我們不能對const 修飾的ic重新賦值的。*//*這樣我們的程序就會更早更容易發現問題了。*//* . . . */
有了const修飾的ic 我們不稱它為變量,而稱符號常量,代表着20這個數。這就是const 的作用。ic是不能在它處重新賦新值了。
認識了const 作用之後,另外,我們還要知道格式的寫法。有兩種:
const int ic = 20;
與
int const ic = 20;
它們是完全相同的。這一點我們是要清楚。總之,務必要記住const 與int哪個寫前都不影響語義。有了這個概念後,我們來看這兩個傢伙:
const int *pi
與
int const *pi
按普通的邏輯看,它們的語義有不同嗎?呵呵,只要記住一點:int 與const 哪個放前哪個放後都是一樣的,就好比const int ic;與int const ic;一樣。也就是説,它們是相同的。
好了,我們現在已經搞定一個“雙包胎”的問題。那麼
int *const pi;
與前兩個語句又有什麼不同呢?下面就來具體分析它們的格式與語義吧。
先來説説const int *pi是什麼作用 (當然int const *pi也是一樣的,前面我們説過,它們實際是一樣的)。看下面的例子:
#include "stdio.h"main(){ /* 代碼開始 */ int i1 = 30; int i2 = 40; /* 現在 pi 變量的內容為 i1 的內存地址 */ const int *pi = &i1; /* 注意這裏,pi可以在任意時候重新賦值一個新內存地址*/ /* pi 變量的內容為 i2 的內存地址 */ pi = &i2; /* 想想看:這裏能用*pi = 80來代替嗎?當然不能!*/ i2 = 80; printf("%dn", *pi); /* 輸出是80 */ /* 代碼結束 */}
語義分析:
看出來了沒有,pi的值是可以被修改的。即它可以重新指向另一個地址的,但是,不能通過*pi來修改i2的值。這個規則符合我們前面所講的邏輯嗎?當然符合了。
首先const 修飾的是整個*pi(注意,我寫的是*pi而不是pi)。所以*pi是常量,是不能被賦值的(雖然pi所指的i2是變量,不是常量)。
其次,pi前並沒有用const 修飾,所以pi是指針變量,能被賦值重新指向另一內存地址的。你可能會疑問:那我又如何用const 來修飾pi呢?其實,你注意到int *const pi中 const 的位置就大概可以明白了。請記住,通過格式看語義。哈哈,你可能已經看出了規律吧?那下面的一節也就沒必要看下去了。不過我還得繼續我的戰鬥。
再看int *const pi
確實,int *const pi與前面的int const *pi會很容易給混淆的。注意:前面一句的const 是寫在pi前和*號後的,而不是寫在*pi前的。很顯然,它是修飾限定pi的。我先讓你看例子:
#include "stdio.h"main(){ /* 代碼開始 */ int i1 = 30; int i2 = 40; int *const pi = &i1; /* pi = &i2; 注意這裏,pi不能再這樣重新賦值了,即不能再指向另一個新地址。*/ /* 所以我已經註釋了它。*/ i1 = 80; /* 想想看:這裏能用 *pi = 80; 來代替嗎?可以,這裏可以通過*pi修改i1的值。(第5行的註釋)*/ /* 請自行與前面一個例子比較。 */ printf("%d", *pi); /* 輸出是80 */ /* 代碼結束 */}
語義分析:
看了這段代碼,你明白了什麼?有沒有發現pi值是不能重新賦值修改了。它只能永遠指向初始化時的內存地址了。相反,這次你可以通過*pi來修改i1的值了。與前一個例子對照一下吧,看以下的兩點分析:
pi因為有了const 的`修飾,所以只是一個指針常量:也就是説pi值是不可修改的(即pi不可以重新指向i2這個變量了)(請看第4行的註釋)。
整個*pi的前面沒有const 的修飾。也就是説,*pi是變量而不是常量,所以我們可以通過*pi來修改它所指內存i1的值(請看第5行的註釋)。
總之一句話,這次的pi是一個指向int變量類型數據的指針常量。
我最後總結兩句:
如果const 修飾在*pi前,則不能改的是*pi(即不能類似這樣:*pi=50;賦值)而不是指pi。
如果const 是直接寫在pi前,則pi不能改(即不能類似這樣:pi=&i;賦值)。
請你務必先記住這兩點,相信你一定不會再被它們給搞糊了。現在再看這兩個聲明語句int const *pi和int *const pi時,呵呵,你會頭昏腦脹還是很輕鬆愜意?它們各自聲明的pi分別能修改什麼,不能修改什麼?再思考下這些問題。
補充三種情況
這裏,我再補充以下三種情況。其實只要上面的語義搞清楚了,這三種情況也就已經被包含了。不過作為三種具體的形式,我還是簡單提一下吧。
情況一:int *pi指針指向const int i常量的情況
#include "stdio.h"main(){ /* begin */ const int i1 = 40; int *pi; pi = &i1; /* 這樣可以嗎?不行,VC下是編譯錯。*/ /* const int 類型的i1的地址是不能賦值給指向int 類型地址的指針pi的。否則pi豈不是能修改i1的值了嗎!*/ pi = (int *) &i1; /* 這樣可以嗎?強制類型轉換可是C所支持的。*/ /* VC下編譯通過,但是仍不能通過 *pi = 80來修改i1的值。去試試吧!看看具體的怎樣。*/ /* end */}
情況二:const int *pi指針指向const int i1的情況
#include "stdio.h"main(){ /* begin */ const int i1=40; const int * pi; pi=&i1;/* 兩個類型相同,可以這樣賦值。很顯然,i1的值無論是通過pi還是i1都不能修改的。 */ /* end */}
情況三:用const int *const pi聲明的指針
#include "stdio.h"main(){ /* begin */ int i; const int * const pi=&i; /*你能想象pi能夠作什麼操作嗎?pi值不能改,也不能通過pi修改i的值。因為不管是*pi還是pi都是const的。 */ /* end */}
-
C語言程序基礎練習題帶答案
C語言傳遞參數均是以值傳遞(passbyvalue),另外也可以傳遞指針(apointerpassedbyvalue)。下面是小編為大家搜索整理的C語言專項訓練題,希望能給大家帶來幫助!更多精彩內容請及時關注我們應屆畢業生考試網!單選題1).下列關於標識符的説法中錯誤的是A.合法的標識符...
-
C語言在屏幕中顯示內容
C語言你瞭解多少呢?你知道C語言在屏幕中顯示內容是什麼樣的嗎?歡迎大家閲讀!更多相關信息請關注相關欄目!我們有兩種方式從計算機獲得信息:一是看屏幕上的文字、圖片、視頻等,二是聽從喇叭發出來的聲音。讓喇叭發出聲音目前還比較麻煩,我們先來看看如何在屏幕上顯示一...
-
C語言基礎循環結構
引導語:循環結構可以減少源程序重複書寫的工作量,用來描述重複執行某段算法的問題,這是程序設計中最能發揮計算機特長的程序結構。以下是本站小編分享給大家的C語言循環結構,歡迎閲讀學習!1.1for循環結構循環語句的一般表達式是:for(表達式1;表達式2;表達式3)語句2....
-
C語言猴子吃桃問題
猴子第一天摘了若干個桃子,當即吃了一半,還不解饞,又多吃了一個;第二天,吃剩下的桃子的一半,還不過癮,又多吃了一個;以後每天都吃前一天剩下的一半多一個,到第10天想再吃時,只剩下一個桃子了。問第一天共摘了多少個桃子?分析:1)設x1為前一天桃子數,設x2為第二天桃子數,則:x...