2024-09-10|閱讀時間 ‧ 約 21 分鐘

[C]其實很不熟的const

1.常數修飾

const修飾符用於固定變量使其成為常數:

const float pi = 3.14;

pi = 3.14159; /*此行報錯,無法更改常數*/

但其實還是有方法可以修改

const float pi = 3.14;

float *p = π

*p = 3.14159;

/*這樣是可以對pi修改成功的*/

但會跳出warning,原因是const 對目標變數的特性已經被丟棄了

以設計理念來說已經決定將pi常數化

但後續的操作又改變其值

因此這個warning廣意上來說接近error了……(編譯成功,但性質惡劣)


2.const與指標

const亦可以拿來修飾指標

然而根據擺放的位置會有兩種:

const int * p 以及int * const p

兩種宣告方法產生的效果與其意義完全不同

const int * p :對常數的指標,地址上的值不變

int * const p :指標常數化,地址不變

先說明const int * p

int i = 1;

const int * p = &i;

printf(" %d " , *p);
/*輸出結果 :1 */

這時若直接嘗試修改指標指向的值

則會報錯:

*p = 10; 
/*這行是錯的 , 嘗試對*p賦值報錯,原因是該地址上的值被常數化*/

然而可以直接更改變數i 達到更改效果:

int i = 1;

const int * p = &i;

i = 10;/*i是變數,可以更改*/

printf(" %d " , *p);
/*輸出結果 :10*/

另外const int * p 常量化的對象是透過p 訪問的值

因此p 本身也可以更改指向的記憶體區塊

以剛剛的程式碼為例:

int i = 1;

const int * p = &i;

int j = 100;

p = &j ; /*將指標指向j的位址*/

printf(" %d " , *p);
/*輸出結果 : 100*/

此操作合法,成功將p 指向變數j 的記憶體位址

所以再回到這篇筆記最一開始的圓周率pi範例

若在第二行中使用const修飾 *p

就可以完全確保不會有前後矛盾的修改行為:

const float p = 3.14;

const float *p = π

*p = 3.14159; /*不成立,p*/

再來說明int * const p

可以改變指向位址中的值

	int i = 1 ; 
int * const p = &i;
printf("before :%d\\n " , *p);
*p = 10 ;
printf("after :%d\\n" , *p);

/*
輸出:
before :1
after :10
*/

但無法更改指標的指向:

	int i = 1 ; 
int * const p = &i;
int j = 5;
p = &j; /*此行報錯,無法改變p指向的位址*/

還有const int * const p :

先宣告一變數讓p指向它

int i = 1;
const int * const p = &i;
printf("%d \\n" , *p);

/*輸出結果:1*/

望文生義,可以想像這樣的宣告方法

是位址與指標訪問的值都常數化

因此對於改變p的指向或者改變p訪問地址上的值

都是不合法的

int i = 1;
const int * const p = &i;

int j = 100;
p = &j ; /*不合法,指針指向位址已常數化*/

*p = 100 ; /*也不合法,透過p指針訪問的值已常數化*/

3.實例:函數的設計

如果去看一些底層函數的宣告

例如POSIX標準中的open :

int open(const char *pathname, int flags);
int open(const char *pathname, int flags, mode_t mode);

可以看到const char *pathname 也是使用const 進行修飾

使用 const 可以防止意外地修改指標所指向的字符內容

open 函數中pathname 代表文件的路徑名

這個路徑名不應該被修改

因此使用 const 可以保證這個字串在函數內部不會被改變

還有像是字串操作常用的strcpy

原始的函數宣告如下:

char *strcpy(char *dest, const char *src);

對於src 也是使用const

防止意外地修改指標所指向內容

分享至
成為作者繼續創作的動力吧!
© 2024 vocus All rights reserved.