工程師應知道的0x10個問題(15): Typedef

MuLong PuYang
5 min readMar 26, 2022

--

英文參考網址

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

中文參考網址

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

原文翻譯

15. Typedef is frequently used in C to declare synonyms for pre-existing data types. It is also possible to use the preprocessor to do something similar. For instance, consider the following code fragment:

Typedef 頻繁的在C語言中使用來對之前存在的資料型態宣告為同義詞。這也是有可能的使用預處理器來做相似的事情。舉例來說,考慮下方的程式碼片段:

#define dPS struct s *

typedef struct s * tPS;

The intent in both cases is to define dPS and tPS to be pointers to structure s. Which method (if any) is preferred and why?

在這兩個案例的目的是去定義 dPS 與 tPS來當指向結構 s 的指標。哪個方法(如果有的話) 是比較偏向的並且解釋為什麼?

This is a very subtle question, and anyone that gets it right (for the right reason) is to be congratulated or condemned (“get a life“ springs to mind). The answer is the typedef is preferred. Consider the declarations:

這是一個非常微妙的問題,而且任何答對這題的人(要有正確的理由)是可以被恭喜或者是譴責(“找點有意思的事“浮現在腦中)。這個答案是 typedef 是比較好的。 思考下面的宣告:

注1: This is a very subtle question, and anyone that gets it right (for the right reason) is to be congratulated or condemned(“get a life“ springs to mind).,這裡的condemn單字有是譴責的意思,而後面的括號 get a life 有找點有意思的的意味,sprins to mind 用google翻譯有湧現到心中的意思。總體來說,在condemned後面加上括號(“get a life“ springs to mind)這裡我感覺作者有點開玩笑的意味在說不要太專注於這類的C語言語法。當然開玩笑歸開玩笑,這裡其實我無法得知這單純是一個開玩笑的語氣還是其實這也算是個有用的語法知識。這裡如果讀者有更好的譯法或者對作者這段話有更好的見解,歡迎留言告訴我。

dPS p1,p2;

tPS p3,p4;

The first expands to

第一個會被擴展成

struct s * p1, p2;

which defines p1 to be a pointer to the structure and p2 to be an actual structure, which is probably not what you wanted. The second example correctly defines p3 & p4 to be pointers.

定義 p1 會變成指向結構的指標而 p2 會變成一個真正的結構,變成可能不是你想要的。第二個範例正確的定義 p3 & p4 成為指標

自我實作以及理解

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

這裡我們先宣告一個 struct s,裡面只有一個成員int a,接著我們也照原文中宣告#define dPS struct s * 與 typedef struct s * tPS;,並在主程式中用 struct s宣告了一個 s_data,並將成員 a 設為 5,接著我們也跟著原文一樣宣告了 dPS p1,p2; 與 tPS p3,p4;

我們來做第一個測試,我們讓p1與p2分別指向 s_data,p1 = &s_data;
p2 = &s_data;,然後編譯

編譯完之後我們發現出現錯誤

Embedded_system_0x10_issues_0x0f_1.c: In function ‘main’:
Embedded_system_0x10_issues_0x0f_1.c:21:10: error: incompatible types when assigning to type ‘struct s’ from type ‘struct s *’
21 | p2 = &s_data;
| ^

看來 p2 不是指標,接著我們對p2的成員a給予值,然後印出p1的a數值與p2的a數值

我們就可以發現輸出結果為p1的成員a為5,p2的成員a為10。所以當我們宣告成: dPS p1,p2,會如原文所說的擴展成這樣 struct s * p1, p2;,p1還是指標,而p2是一個結構變數

Value of a in p1: 5
Value of a in p2: 10

接著我們將 p3 與 p4 指向s_data,發現都能指成功

接著我們將p3與p4的成員a也都印出來,會發現都是5,tPS p3,p4;這樣宣告確實可以讓p3與p4都是指標

輸出結果

Value of a in p1: 5
Value of a in p2: 10
Value of a in p3: 5
Value of a in p4: 5

--

--