工程師應知道的0x10個問題(1): 用#defince定義一年的秒數

MuLong PuYang
5 min readJan 31, 2022

--

英文原文網址

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

中文參考網址

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

原文翻譯

1. Using the #define statement, how would you declare a manifest constant that returns the number of seconds in a year? Disregard leap years in your answer.

使用#define敘述,你會如何如何宣告一個明顯的常數來回傳一年的秒數數量? 在你的答案中忽略閏年

#define SECONDS_PER_YEAR (60UL * 60UL * 24UL * 365UL)

I’m looking for several things here:

我會從這裡看到許多事情:

(a) Basic knowledge of the #define syntax (i.e. no semi-colon at the end, the need to parenthesize etc.).

(a) 對於#define語法的基礎知識(例如: 不需要在尾端加分號,對括號的需求等)

(b) A good choice of name, with capitalization and underscores.

(b) 好的名子的選擇,有大寫以及底線

(c) An understanding that the pre-processor will evaluate constant expressions for you. Thus, it is clearer, and penalty free to spell out how you are calculating the number of seconds in a year, rather than actually doing the calculation yourself.

(c) 了解到預處理會去計算常數運算式。所以簡潔、無懲罰的拼出你是如何計算一年的秒數的數量,而不是真正的由你自己計算

(d) A realization that the expression will overflow an integer argument on a 16 bit machine — hence the need for the L, telling the compiler to treat the expression as a Long.

(d) 理解到運算式可能會在一個16 bit的機器上對整數產生溢位,因此需要L,告訴編譯器對待運算式為Long

(e) As a bonus, if you modified the expression with a UL (indicating unsigned long), then you are off to a great start because you are showing that you are mindful of the perils of signed and unsigned types — and remember, first impressions count!

(e) 當一個bonus,如果你更改運算式為UL(意指unsigned long),你會有一個好的開始,因為你注意到了signd與unsigned型態的危險,並且記住,第一印象很重要

自我實作以及理解

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

首先我們使用這篇文章的標準答案,宣告一個巨集,來打印出結果

#define SECONDS_PER_YEAR (60UL * 60UL * 24UL * 365UL)

輸出結果

31536000

那如果我們是在Ubuntu 20.04的64位元系統中,使用以下的預處理

#define SECONDS_PER_YEAR (60 * 60 * 24 * 365)

我們將程式改成如下

我們用gcc編譯的話,會出現以下的warning

Embedded_system_0x10_issues_0x01_2.c: In function ‘main’:
Embedded_system_0x10_issues_0x01_2.c:7:15: warning: format ‘%lu’ expects argument of type ‘long unsigned int’, but argument 2 has type ‘int’ [-Wformat=]
7 | printf("%lu\n", SECONDS_PER_YEAR);
| ~~^
| |
| long unsigned int
| %u

看來我們把打印的format改成%d

輸出結果

31536000

那我們如果把括號拿掉,依然使用%lu的format呢

依然會有warning

Embedded_system_0x10_issues_0x01_4.c: In function ‘main’:
Embedded_system_0x10_issues_0x01_4.c:7:15: warning: format ‘%lu’ expects argument of type ‘long unsigned int’, but argument 2 has type ‘int’ [-Wformat=]
7 | printf("%lu\n", SECONDS_PER_YEAR);
| ~~^
| |
| long unsigned int
| %u

最後我們就把%lu改成%d

輸出結果

31536000

--

--