const一詞是英文constant的縮寫,設立這個關鍵字的本意,是希望讓它所修飾的物件成為乙個常量。記得在國家間的外交中,有乙個經常用到的術語:「從事與身份不符的活動」,這個const恰恰也正從事著這樣的活動,呵呵。c語言可以有三種方法定義乙個常量:#define、const和列舉,但只有列舉才是真正的常量,什麼是真正的常量?真正的常量是沒有儲存空間的,是乙個右值,這意味著通過任何合法的手段也不會被修改,但被const修飾的物件依然是乙個左值,儘管這個物件被const限定,筆者仍然至少可以找到三種合法的手段去修改它,而#define所做的只不過是編譯期替換而已,只有列舉常量才能真正做到這一點。const實在不應該被命名為const,這會讓人們產生誤解,它應該命名為readonly或類似的字眼,意即不能通過被const修飾的物件修改它所指向的物件或者它所代表的物件。但在c的世界裡把const稱為常量早已是普遍的現象,那我們就只好隨大流咯,也稱之為常量吧,只要知道它實際上不是真正的常量就行了。
第七章曾經討論過const int *p;與int * const p的區別,這兩個宣告的中文名稱常常搞得混亂不堪。第乙個宣告的const是宣告說明符,它修飾p所指向的物件,但p仍然是可變的,這意味著p是乙個指向常量的指標,簡稱常量指標。第二個宣告的const是宣告符的一部分,它修飾的物件是p,這意味著p是乙個常量,而且是乙個指標型別的常量,簡稱指標常量。指標常量又常常被人稱為「常指標」或「常指標變數」,常指標變數這個名稱有點蹩腳,又常又變的,容易讓人摸不著頭腦,最好還是不要這樣稱呼。這裡還得再強調一次指標常量與位址常量是不同的,不能把陣列名稱為指標常量,也不能把指標常量稱為位址常量,因為指標常量依然是乙個左值,而陣列名是乙個右值,這裡肯定有人會問:「什麼?指標常量是乙個左值?我沒聽錯吧?」你的確沒有聽錯,c89對於左值是這樣定義的:
物件是乙個命名的儲存區域,左值(lvalue)是引用某個物件的表示式。
換言之,如果乙個表示式引用的是乙個具有具體儲存空間的物件,它就是乙個左值!那麼既然指標常量是乙個左值,為什麼卻不能給它賦值呢?是因為它受限於賦值表示式的一條規則:賦值表示式的左值不能含有限定詞!
為了防止指標指向的常量被修改,c標準對於指標間賦值有乙個規定,就是左值必須包含右值的所有限定詞。 這就限定了乙個指向const物件的指標不能賦值給指向非const物件的指標,但反過來就允許。這個規定初看上去非常合理,但其效用其實只限於一級指標,二級指標間的賦值即使滿足規定也不再安全,下面舉個例子:
const int i=10;
const int **p1;
int *p2;
p1 = &p2;
*p1 = &i;
*p2 = 20;
現在你會發現,作為常量的i的值被修改了。i的值被修改的關鍵原因在*p1=&i;這一句,&i是乙個指向常量的一級位址,如果沒有二級指標p1,受限於上述規定,作為左值接受這個一級位址的指標就必須也是乙個指向常量的一級指標,於是就不能進行下一步賦值20的操作。因此,正由於指向const物件的二級指標p1的出現,使得*p1也是乙個指向const的指標,於是*p1=&i能夠合法地執行,常量i的值被修改也就成了乙個預想中的結果了。有鑑於此,某些編譯器也會限定非const二級指標之間的賦值,規定上面的p1=&p2也是非法的。
第七章介紹宣告符的指標部分有一種形式:
* 型別限定符表opt 指標
這種形式產生了一種比較複雜的帶const的指標,例如:
const int * const *** const ** const p;
這是乙個會讓人頭暈目眩的表示式,宣告符部分巢狀了九次,如何辨認誰是const,誰不是const呢?一旦明白了其中的原則,其實是非常簡單的。第一和最後乙個const大家都已經很熟悉的了。對於藏在一堆*號中的const,有乙個非常簡單的原則:const與左邊最後乙個宣告說明符之間有多少個*號,那麼就是多少級指標是const的。例如從右數起第二個const,它與int之間有4個*號,那麼p的四級部分就是const的,下面的賦值表示式是非法的:
**p = (int *const***)10;
但下面的賦值是允許的:
***p=(int*const**)10;
從左邊數起第二個const,它與int之間有1個*,那麼p的一級部分是const的,也就是*****p = (int*const***const*)10;是非法的。
第九章 指標與const
const一詞是英文constant的縮寫,設立這個關鍵字的本意,是希望讓它所修飾的物件成為乙個常量。記得在國家間的外交中,有乙個經常用到的術語 從事與身份不符的活動 這個const恰恰也正從事著這樣的活動,呵呵。c語言可以有三種方法定義乙個常量 define const和列舉,但只有列舉才是真正的...
第九章(筆記)
轉移指令是可以修改ip,或同時修改cs和ip的指令 offset 是用於提取標號偏移位址的操作符 jmp在第2章裡說到時用於修改ip或同時修改cs和ip的轉移指令,這章裡單獨的jmp指令是乙個無條件的轉移指令 jmp short 標號 是實現段內短轉移 jmp near ptr 標號 是實現段內近轉...
第九章作業
班級 0401304 學號 2013211526 姓名 鄧小俊 2.身份驗證 依據使用者所提供的身份資訊,來進行登入驗證,可以再細分為使用者是否可以登入sql sever 使用者是否可以登入到指定的目標資料庫等。授權 已通過身份驗證的使用者,檢查其所被賦予的許可權,是否可以訪問或者執行目標的物件 3...