C的關鍵字——const的理解和用法
進入原貼討論:http://bbs.bccn.net/thread-66030-1-1.html
關於C的關鍵字——const的理解和用法
const在C中的用法很靈活(相信C++中也一樣),個人感覺對之既愛又恨,有時候感覺const很好用,同時又經常會因為它的優點而犯錯,犯錯的原因除了粗心之外,另一個更重要的,就是以前對const理解不到位。於是今天自己寫成一篇小總結。如果是初學者,建議好好看一下,相信幫助比較大;如果是高手,請不吝賜教!
上面寫了一段廢話,就算是小序吧:)接下來就是正文;
一、關於const的具體定義:
——個人感覺很難對它下一個標準的定義,因為的用法很靈活,似乎對它定義後總無法讓人能夠明白它的意思,而且容易讓人產生誤解(也許是偶水準太菜了)。例如,把它有定義:一個能夠讓變數變成無法修改的常量的關鍵字。那麼,這樣的話,就可能讓人誤解為只要有const在定義變數裡面,那變數就無論怎樣都無法修改。這樣的理解是很片面的(下面用法方面將對這問題做探討)。因此,本人在此不敢對它下定義,其他參考書好象也沒有下定義。
二、關於const的具體作用
——const作用就靈活了,一個運算式中const放置的位置不同,效果可能就不一樣了。下面分具體情況分析(當然,所舉的情況並非覆蓋全部情況)
A。const最經常的用法
1.為了防止傳遞的函數參數不被修改,在調用函數的形參中用const關鍵字.
int FindNum(const int array[], int num, int conut);//聲明函數
//code...
int FindNum(const int array[], int num, int count)
{
int i;
int flag = 1;
for (i = 0; (i < count) && flag; i++)
{
if (array[i] == num)
{
flag = 0;
break;
}
}
return flag;
}
//code...
上面這例子中,編譯器會把array[]當作常量資料的陣列看待。所以,假如你不小心給陣列賦值,那麼,編譯器就會報錯了。因此,當你不需要也不想修改陣列的資料時,最好用const把陣列定義為常量陣列。
2.const可以用來創建陣列常量、指標常量、指向常量的指標等:
const char ch = 'a';
const int a[5] = {1, 2, 3, 4, 5};
const int *p = a; //a是一個陣列的首位址.p是指向常量的指標
int * const p = a; //a是一個陣列的首位址.p是指針常量;
const int * const p = a; //a是一個陣列的首位址。p是指向常量的指標常量
前兩種情況很簡單,現在著重分析一下後三種用法,因為這3種情況容易出錯,偶就有時候怕用錯了。
剛脆不用const.
const int *p = a;
p是指向常量的指標,因此,不可以通過給指標賦值來改變陣列中的資料,例如:
// *p = 10; /*錯誤*/
// *(p + 2) = 1; /*錯誤*/
假如指向常量指標可以改變值,那麼,就等於也改變了陣列的數。
據了。假如你不理解,偶倒有一個辦法讓你理解,你就想你和一個人綁在一起,有可能你移動了位置而他不跟著你移動嗎!哈哈
int * const p = a;
看這運算式,const的位置和第一個不同吧!他們的用法和作用就完全不一樣了。這時候p是指標常量,我們知道,指標是指向了一個陣列的首位址,那麼,它的位置就不可以改變了。但是你現在應該和第一個運算式比較了,現在的陣列並不是常量陣列,所以陣列的資料是可以改變的,而指標這時候它是不可以移動的,指向陣列第一個資料,所以它可以而且只可以改變陣列第一個 數據的值。這一點請別誤解,指標常量只是它的位址不可以改變,並不是它指向的內容一定不可以改變,這一點切記!
好啦。假如你又不理解,又有一個比較形象的例子來說明:假如有一個固定的人拉著另外一個人的手,注意,固定的人相當於他是不可以由其他人來替換的。但是他可以拉其他人的手啊, 並不一定規定他必須拉同一個人的手啊。現在你應該可以有個比 較深的印象和理解吧
下面舉幾個例子幫助理解:
// *p = 2; /*可以*/
// *(p+1) = 10; /*可以*/
// p++; /*不可以*/
const int * const p = a;
//假如前面兩種運算式的本質你理解了,這種運算式你來理解根本沒有問題,const現在有兩個,而且一個const的位置是第一種情況的位置,第二個const是第二種情況的位置,所以這運算式的功能就是前兩種情況的作用總合。這裡不多說!
下面舉幾個例子幫助理解:
// *p = 2; /*不可以*/
// *(p + 2) = 10; /*不可以*/
// p++; /*不可以*/
B。const並不會阻止參數的修改
之所以把這作為一點來談,就是因為有一些朋友可能會以為在函數參數中用了const就一定不可以改變參數,這實際上是錯誤的理解,因為,它並不阻止參數的修改,下面舉個簡單的例子來闡述一下;
#include<stdio.h>
#include<ctype.h>
void ChangeStr(const char *String);
int main(void)
{
char str[] = "The C programme";
Change(str);
printf(str);
system("Pause");
return 0;
}
void ChangeStr(const char *String)
{
char *Source = (char *)String;
while (*Source)
{
*Source = toupper(*Source);
Source++;
}
}
//end
上面的程式把字串中的每個字元都轉換成大寫字母了。因為*String把地址給了*Source,而*Source的值的改變編譯器並不干涉,可能有的編譯器會發出警告之類。上面的程式只是為了說明const並不會阻止參數的修改,如果象上面程式那樣,個人感覺沒什麼意義,只會讓人容易混亂而已。
關於CONST的用法和理解本人也就只能說這麼多了,當然,很可能有更多高級或者少用的用法,由於水準和經驗有限,確實不能再說些什麼。
三、參考文獻
——《C primer plus 5th》
ID: lj_860603
整理於2006.5.21

感謝分享!!
謝謝分享 : )
感謝釐清觀念
感謝您的分享~
謝謝你^^
寫得很清楚 不過"為了防止傳遞的函數參數不被修改"不是是雙重否定吧
不是原文作者>< 不過語意應該就如大大說的 "為了防止傳遞的函數參數被修改" ~
const int *p = a; p是指向常量的指標,因此,不可以通過給指標賦值來改變陣列中的資料,例如: // *p = 10; /*錯誤*/ // *(p + 2) = 1; /*錯誤*/ 請問一下這種狀況下 p++ 是不是可以成立呢? 謝謝!
const int *p 表示p常量變數指標 是不能修改指向位置的儲存值 若 int * const p = a; const為p的指標位置,故不能修改指標位置p++,但可以修改指向記憶體的儲存值
#include
#include
int main(void)
{
const char ch = 'a';
int i,a[6] = {1, 2, 3, 4, 5,6};
const int *p = a;
p++;
printf("此時*p已更改位置到第二個值:%d\n",*p);
getch();
}
//end
/*經實驗確認p只是由指向第一個值,變成指向第二個值。
所以const int *p的寫法只是使你無法藉由*p改變陣列a的內容值。
本身p的值還是可以更改的*/
#include
int main(void) {
int p = 10;
const int *ptr1=&p;
int **ptr2=0;
ptr2=&ptr1;
printf("p 的值:%d\n", p);
printf("藉由**p改變p的值");
**ptr2=20;
printf("p 的值:%d\n", p);
printf("p的記憶體位置:%X\n\n", &p);
printf("*ptr1 = %d\n", *ptr1);
printf("ptr1 = %X\n", ptr1);
printf("ptr1 的記憶體位置:%X\n\n", &ptr1);
printf("**ptr2 = %d\n", *ptr2);
printf("*ptr2 = %X\n", *ptr2);
printf("ptr2 = %X\n\n", ptr2);
puts("整理(誰儲存了誰?):");
printf("&p = %X\tprt1 = %X\n", &p, ptr1);
printf("&ptr1 = %X\tprt2 = %X\n", &ptr1, ptr2);
getch();
return 0;
}
/*有趣的是 如果你定義了const int *ptr1 雖然你不可以藉由const int *ptr1
改變p的值,可是你還是可以定義一個 int **ptr1(指標變數的指標) 去改變p的值
*/
不好意思 第22行 printf("**ptr2 = %d\n", **ptr2); 少加了一個*符號。
感謝實驗~:)
*****
*****
(char *) = (const char *) 在 C 是 warning 在 Cpp 是 error 要證明 const 可更改應該要用像這樣的例子才對: char *cstring; const char *ccstring = (const char *)cstring; cstring = "abc"; printf("%s", ccstring); // abc cstring = "cba"; printf("%s", ccstring); //cba 所以被 const 並不代表值不會變 只是不能修改它而已
感謝補充!!!
有看沒有懂 果然還是得要有基礎才比較好理解 const char print(str) 許多指令我都不懂啊 什麼時候要控格 什麼時候逗號或分號 我知道是句尾 但有時似乎句尾也沒每行都有打鬥號或分號 還有*字號用法 感恩
你應該從基本的程式書看起 照範例打 執行玩玩再修改看看 我也程式不是強者 不過程式每行意結束是分號 逗號應該是區別參數 變數等...
*****
thx ~ it helps
c語言的const是執行時期編譯的 所以可以讀內存修改 所以不能const int num=10; int array[num]; c++ const是編譯時期時編譯的 會轉到符號表 讀內存修改就沒有用 所以c++就可以這樣寫 const int num=10; int array[num];
thank you~