工程師應知道的0x10個問題(7): Const的用法

MuLong PuYang
10 min readFeb 27, 2022

--

英文原參考網址

A ‘C’ Test: The 0x10 Best Questions for Would-be Embedded Programmers

中文參考網址

C語言測試 應知道的0x10個基本問題

原文翻譯

7. What does the keyword const mean?

Keyword const代表什麼?

As soon as the interviewee says ‘const means constant’, I know I’m dealing with an amateur. Dan Saks has exhaustively covered const in the last year, such that every reader of ESP should be extremely familiar with what const can and cannot do for you. If you haven’t been reading that column, suffice it to say that const means “read-only”. Although this answer doesn’t really do the subject justice, I’d accept it as a correct answer. (If you want the detailed answer, then read Saks’ columns — carefully!).

當應試者回答說 ‘const就是常數’,我知道我會認為他們是業餘的。Dan Saks去年已經辛苦的概括const,因此每一個ESP(Embedded System Programming)的讀者應該要很熟悉 const 對你而言可以做什麼以及不能做什麼。如果你還沒有讀到這個專欄,只要說 const 代表 “read-only” 就夠了。雖然這個答案並不是完全,但我接受它是一個正確的答案。(如果你想要知道更詳細的答案,那仔細的就去讀Saks的專欄)

If the candidate gets the answer correct, then I’ll ask him these supplemental questions:

如果應試者回答問題正確,那麼我就會問他這些附加的問題

What do the following incomplete [2] declarations mean?

這些未完成的宣告代表什麼?

[2]的原文如下
[2] I’ve had complaints that these code fragments are incorrect syntax. This is correct. However, writing down syntactically correct code pretty much gives the game away.

const int a;

int const a;

const int *a;

int * const a;

int const * a const;

The first two mean the same thing, namely a is a const (read-only) integer. The third means a is a pointer to a const integer (i.e., the integer isn’t modifiable, but the pointer is). The fourth declares a to be a const pointer to an integer (i.e., the integer pointed to by a is modifiable, but the pointer is not). The final declaration declares a to be a const pointer to a const integer (i.e., neither the integer pointed to by a, nor the pointer itself may be modified).

前兩個代表同一件事情,也就是說 a 是個 const (read-only) 整數。第三個代表 a 是個指向 const int 的指標(意即,整數無法修改,但是指標可以)。第四個宣告 a 是個指向整數的 const 指標(意即,被指到的整數可以修改,但是指標沒辦法)。最後一個宣告 a 是代表 const 指標指到 const integer(意即,被 a 指到的整數,或者是指標本身都無法修改)

If the candidate correctly answers these questions, I’ll be impressed.

如果應試者正確的回答這些問題,我會印象深刻

Incidentally, one might wonder why I put so much emphasis on const, since it is very easy to write a correctly functioning program without ever using it. There are several reasons:

附帶一提,你可能會好奇為什麼我會放這麼多強調在 const ,畢竟即使不用這個,也還是可以很容易的寫出正確功能的函數。主要有以下幾個原因

(a) The use of const conveys some very useful information to someone reading your code. In effect, declaring a parameter const tells the user about its intended usage. If you spend a lot of time cleaning up the mess left by other people, then you’ll quickly learn to appreciate this extra piece of information. (Of course, programmers that use const, rarely leave a mess for others to clean up…)

(a) 使用 const 概括一些非常有用的資訊對那些正在讀你程式的人。實際上,宣告一個 parameter const 會告訴使用者關於它的預期使用。如果你付了很多時間在清理其他人留下的混亂,你將會更快的學到感謝這個多餘的訊息。(當然,程式設計師使用 const ,很少會留下混亂給其他人清理)

(b) const has the potential for generating tighter code by giving the optimizer some additional information.

(b) Const有潛力產生更緊湊的程式碼藉由給予優化器一些附加資訊

(c) Code that uses const liberally is inherently protected by the compiler against inadvertent coding constructs that result in parameters being changed that should not be. In short, they tend to have fewer bugs.

(c) 使用 const 的程式碼自然的是固有的被編譯器保護來對抗不注意的程式結構導致不該改變的參數被改變。簡而言之,它們傾向擁有更少的bug

自我實作以及理解

注1: 以下是我的自我實作以及理解的部分,不保證正確而且很有可能描述不清楚或者是有錯誤,讀者若發現有可以更正的地方也歡迎留言告訴我注2: 以下皆簡單的使用Ubuntu 20.04虛擬機做測試,並非真實的嵌入式系統,所以Ubuntu 20.04出來的成果可能會與嵌入式系統上的有差異注2: 以下皆簡單的使用Ubuntu 20.04虛擬機做測試,並非真實的嵌入式系統,所以Ubuntu 20.04出來的成果可能會與嵌入式系統上的有差異

(一) const int a;

編譯結果

Embedded_system_0x10_issues_0x07_1.c: In function ‘main’:
Embedded_system_0x10_issues_0x07_1.c:6:7: error: assignment of read-only variable ‘a’
6 | a = 20;
| ^

我們可以發現無法改變變數 a 的數值

(二) int const a;

Embedded_system_0x10_issues_0x07_2.c: In function ‘main’:
Embedded_system_0x10_issues_0x07_2.c:6:7: error: assignment of read-only variable ‘a’
6 | a = 20;
| ^

我們可以發現無法改變變數 a 的數值

(三) const int *a;

這裡我們宣告一個 const int *a,另外宣告一個 int b = 7,讓 *a 指向 b,接著再更改 *a 的數值,我們會發現編譯結果是過不了的,因為這裡是個指向 const int 的指標

編譯結果

Embedded_system_0x10_issues_0x07_3.c: In function ‘main’:
Embedded_system_0x10_issues_0x07_3.c:9:8: error: assignment of read-only location ‘*a’
9 | *a = 8;
| ^

但是我們可以更改指到的變數,下方的程式碼,我們一開始讓 *a 指到 b,印出 b 的數值,接著我們可以讓 *a 指到 c,並印出 c 的數值

輸出結果

7
8

(四) int * const a;

首先我們讓 *const a 一開始就指到 b,這時我們先印出 b 的數值,接著我們再讓 *a 的數值改變成 8,都可以順利修改

Before modification: 7
Before modification: 8

那麼如果我們讓 *const a 指到其他的變數呢?,編譯結果是不通過的

編譯結果

Embedded_system_0x10_issues_0x07_4_2.c: In function ‘main’:
Embedded_system_0x10_issues_0x07_4_2.c:10:7: error: assignment of read-only variable ‘a’
10 | a = &c;
| ^

(五) int const * a const;

注: 這邊由於我再Ubuntu 20.04的GCC寫這種格式是有問題的,所以以下我會使用const int* const a這樣的格式,如果有對測試int const * a const這種格式發現是可以通過的讀者,歡迎再留言告訴我

這裡我使用const int* const a

首先我們宣告一個變數 b = 7,然後讓 const int* const a 指到這個變數並印出

輸出結果

7

接著我們嘗試更改 *a 的數值為 8

編譯結果為不能修改

Embedded_system_0x10_issues_0x07_5_2.c: In function ‘main’:
Embedded_system_0x10_issues_0x07_5_2.c:8:8: error: assignment of read-only location ‘*a’
8 | *a = 8;
| ^

接著我們再嘗試更改 *a 所指到的變數

編譯結果為不能修改

Embedded_system_0x10_issues_0x07_5_3.c: In function ‘main’:
Embedded_system_0x10_issues_0x07_5_3.c:10:7: error: assignment of read-only variable ‘a’
10 | a = &c;
| ^

--

--