iT邦幫忙

2026 iThome 鐵人賽

DAY 6
0
自我挑戰組

韌體工程師的不只 0x10 個問題系列 第 6

Day 6 - 不能改變值的 const 跟 literal

  • 分享至 

  • xImage
  •  

constliteral 的值都不能被改變,看似功能相同,但其本質上的意義還是有落差,我們可以從賦值符號 = 切分為左右邊來認識兩者。

const

const 代表「變數」宣告後不可改變其值,之所以強調「變數」,是因為其仍有自己的名稱跟記憶體位址,位在賦值符號 = 的左邊(左值)。

舉例來說:

const int a = 10;

先來看 = 符號左邊:

  • const 是修飾符,表示後面接的變數值不能被改變。
  • int 表示變數為整數型別。
  • a 是變數的名稱。

這裡已經用 const 表示 a 這個整數變數的值不能修改,因此如果寫:

const int a = 10;
a = 5;
printf("%d", a);

會跑出如下錯誤訊息:

main.c: In function ‘main’:
main.c:14:7: error: assignment of read-only variable ‘a’
   14 |     a = 5;
      | 

不過如果要顯示變數 a 的記憶體位址:

const int a = 10;
printf("%p", &a);

是可以正常運作的!

補充:const 不保護型別

正當我以為自己清楚已經知道 const 的功能,參加一場面試時卻被問「那型別也能保護嗎?」。當下的我答不出來,只好回家後立刻查資料、做實驗。

後來發現答案是否,例如:

const int a = 10;
float b = (float)a;
printf("%f", b);

是不會報錯的,被 const 保護的 int a 依然被成功轉為 float 型別,可見 const 只能確保變數的「值」不被改變,而不包含型別。

literal

literal 則是單純代表一個固定的值,沒有名稱、也沒有記憶體位址,位在賦值符號 = 的右邊(右值)。

以下寫法都有用到 literal

const int a = 10;
int a = 10;

= 符號右邊的 10 都是 literal,這兩個 10 都不能再被修改,永遠是 10

literal 不能取址,因此如果寫:

const int a = 10;
printf("%p", &10);

會跑出:

main.c: In function ‘main’:
main.c:6:18: error: lvalue required as unary ‘&’ operand
    6 |     printf("%p", &10);
      |                  ^

表示 & 只能對左值(也就是變數)取址。

所以到底能不能改?

在剛剛的範例中:

int a = 10;

= 左邊沒有寫 const,看起來可以改啊,怎麼又說值不能改,永遠是 10

  • 可以改的是「左值」,也就是整數變數 a
  • 不能改變的是「右值」,也就是 10 這個值。

在沒有寫 const 的時候,左值可以改、右值不能改;同理左值可以取址、右值不能取址。

而如果要讓左值不能改,就在左邊的 int 前或後加上 const

跟指標結合

現在我們把 const 跟萬惡的指標結合,來看看可以變出什麼花樣。

比較與記憶方式

宣告方式 指標本身可變(可改指別的) 指向的值可變
const int a;int const a; 無指標,略 X
const int * a;int const * a; O X
int * const a; X O
const * int a; 無效語法 無效語法
const int * const a; X X

透過上表,可以歸納如下:

首先是最簡單的「無指標」情況,代表值不能改。

再來,只要判斷 const 跟誰靠比較近就是修飾誰(表示誰被鎖定不能改):

  • constint(或其他資料型別)比較近,代表修飾的是指向的值,int 可以寫在 const 的前面或後面,因此寫成 const int * a;int const *a; 皆可,範例如下:
int x = 5, y = 6;
const int *a = &x; // const 貼著 int,表示指向的值不能改
a = &y;            // 指標 a 可以從指向 x 的記憶體位址改成指向 y 的記憶體位址
// *a = 7;         // 指標 a 指向的值 *a (也就是 5)不能改
  • 如果 consta 比較近,就代表修飾 a 指標本身,指標不能改指其他地方。a 不能寫在 const 前面,所以只會有 int * const a; 一種情況,範例如下:
int x = 5, y = 6;
int * const a = &x; // const 貼著 a,表示指標 a 存的位址不能改
// a = &y;          // 指標 a 不能改指向 x 之記憶體位址外的其他地方
*a = 7;             // 指標 a 指向的值 *a (也就是 5)可以改

const int * const a;inta 都相鄰於 const,因此指標本身與被指向的值都不能改。

值得留意的是,若 const 沒有跟 inta 相鄰,就是無效語法,例如 const * int a;

參考資料

  1. 韌體工程師的0x10個問題
  2. Constants in C (GeeksforGeeks)
  3. Difference Between Constant and Literals (GeeksforGeeks)

上一篇
Day 5-靜態變數與靜態函數
系列文
韌體工程師的不只 0x10 個問題6
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言