工程師應知道的0x10個問題(16): a++的問題

MuLong PuYang
7 min readMar 26, 2022

--

英文參考網址

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

中文參考網址

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

原文翻譯

16. C allows some appalling constructs. Is this construct legal, and if so what does this code do?

C語言允許一些可怕的結構。這個結構合法嗎? 如果合法的話這段程式碼會做什麼?

int a = 5, b = 7, c;

c = a+++b;

This question is intended to be a lighthearted end to the quiz, as, believe it or not, this is perfectly legal syntax. The question is how does the compiler treat it? Those poor compiler writers actually debated this issue, and came up with the “maximum munch” rule, which stipulates that the compiler should bite off as big a (legal) chunk as it can. Hence, this code is treated as:

這個問題是為這個測驗的一個愉快的結束。不管你相信或不相信,這是個完全的合法語法。這個問題是編譯器如何處理它? 那些不好的編譯器作者實際上爭論這個問題。根據 “maximum munch”規則,明確說明編譯器應該要盡可能地咬掉最大的一個(合法個)chunk。因此,這個程式碼要被處理為:

注1: 這裡的came up with the “maximum munch” rule,雖然come up with是提出的意思,中文來源這裡是翻成根據,這邊若翻成根據的話整體文義會順很多,所以這裡採用中文來源的譯法注2: “maximum munch” rule,這裡在中文來源是翻成最處理原則,這邊如果用google搜尋的話,會出現Maximal munch的維基頁面,而google的機器翻譯是翻成最大匹配度注3: which stipulates that the compiler should bite off as big a (legal) chunk as it can。這邊我直接直譯成譯器應該要盡可能地咬掉最大的一個(合法個)chunk,而中文來源是翻成: 編譯器應當能處理儘可能所有合法的用法。當然事實上這句話的意思有可能是偏盡可能處理的意味在。對於這段文字如果讀者認為有更好的譯法的話,歡迎留言跟我說

c = a++ + b;

Thus, after this code is executed, a = 6, b = 7 & c = 12;

因此,在這個程式碼執行之後,a = 6, b = 7 & c = 12;

If you knew the answer, or guessed correctly — then well done. If you didn’t know the answer then I would not consider this to be a problem. I find the biggest benefit of this question is that it is very good for stimulating questions on coding styles, the value of code reviews and the benefits of using lint.

如果你知道這個答案,或者是猜對 — 那做得好。如果你不知道這個答案那麼我不會認為這是一個問題。我發現這個問題的最大益處是這是個非常好的激勵問題在於程式風格,程式碼審查的價值以及使用lint的益處。

注1: 文章的lint我想應該是指一種C語言的分析工具,以下文章有對這個工具的簡介
代码的 Lint 是什么意思

最後這段文字其實與這個問題無關,算是原作者對於這16個嵌入式工程師該應知道的問題所做的一個結尾

Well folks, there you have it. That was my version of the C test. I hope you had as much fun doing it as I had writing it. If you think the test is a good test, then by all means use it in your recruitment. Who knows, I may get lucky in a year or two and end up being on the receiving end of my own work.

好的大夥,你已經擁有它了。這是我的版本的C語言測試。我希望你當你在做的時候擁有跟我在寫的時候一樣多的樂趣。如果你認為這個測試是好的測試,那麼當然可以使用它在你的招聘。誰知道呢? 我可能會在一兩年內很幸運但最終我自己工作承受不愉快的事物

注: being on the receiving end有承受不愉快事物的意思,所以Who knows, I may get lucky in a year or two and end up being on the receiving end of my own work.這句話這裡我就翻成: 誰知道呢? 我可能會在一兩年內很幸運但最終我自己工作承受不愉快的事物。這裡我想作者在這裡表達的意思應是日無千日好,花無百日紅的感慨,畢竟專業能力是一部分,職場的問題又是另外一部份
這邊同樣的如果讀者認為有更好的譯法,歡迎留言跟我說

自我實作以及理解

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

這裡我們照著原文宣告a = 6,b = 7,接著讓 c = a+++b。

這裡實際上 a會先與b相加,所以是5+7=12,c的數值是12,b的數值不會變是 7,a跟b加完之後,接著會a++,所以a變成6,其實a++就是後做,先運算完之後再++,所以才會5加完7之後,a自身才++變成6

輸出結果

a: 6, b: 7, c: 12

a++與++a

a++與++a是個經典的問題,如果我們去google的話大都是寫成i++與++的比較

以下有兩篇文章讀者可以參考

C 語言中的 i++ 與++i
What is the difference between ++i and i++?

這裡我們讓 c = a++的話,則c會等於5,接著a++再運算,a變成6

然後接著我們讓c = ++b,++b會先運算,所以b會等於8,而c當然接收8的數值,所以數值為8

輸出結果

a: 6, b: 7, c: 5
a: 6, b: 8, c: 8

接下來我們試試看 a++或++a這類的型態在printf的輸出強況

我們一開始先printf(“a: %d\n”, a++);,這時候a還沒有++,所以輸出的數值為5,接著我們再印一次,這時候a已經++過了,所以數值會變成6

而接著printf(“b: %d\n”, ++b);我們對++b的數值打印出來,這時候b已經++過了,所以數值為8,再印一次b,當然數值也是為8

輸出結果

a: 5
After a++, a: 6
b: 8
After ++b: 8

--

--