看板 C_and_CPP 關於我們 聯絡資訊
A) 首先 line 16 輸出 error 才是正常的 ptr 的型別是 void* 因此 *ptr 會對應到 void 但是 void 是 incomplete type 所以只能屬於 default B) C11 加入 _Generic 關鍵字是神奇的進展 前處理器只做簡單的字串處理 完全不會涉及到判斷 macro argument 的型別 如果要在前處理階段時完成會使設計難度大增 因此時至今日 _Generic 仍然在編譯階段處理 _Generic 的語法如下: _Generic(controlling-expression, association-list) where association-list | type-name ':' expression [yacc syntax, (LA)LR] | association-list type-name ':' expression 事實上這並沒有想像中的糟 O.O 早期工程師遇到這種問題時 設計出了一套 hack 的方法 (compiler-dependent, GCC) #define is_of(x, t) (__builtin_types_compatible_p(__typeof__(x), t)) #define print(x) do { if (is_of(x, int)) \ printf("num = %d\n", x); \ else if (is_of(x, char)) \ printf("char = %c\n", x); \ else abort(); } while (0) int main (void) { char c = 'a'; int n = 10; float f = 1.2; print(n); // shows: num = 10 print(c); // char = a print(f); // Aborted (core dumped) } 這乍看下完美解決這個問題 但是當這樣的需求越來越大的時候 被編入語言標準的可能性就會大增 好確保能跨平臺使用沒問題 C) 原本的寫法會觸發編譯警告 雖然 _Gerenic 是 Generic Selection 沒錯 但是編譯器還是會在所有的 expression 裡檢查語意的正確性 由於輸入的型別並非固定 要同時滿足 printf 的 format specifier 本質上是不可能的 如果按照原先的代碼可能會產生 Wcast-align (Clang) 或是 Wstrict-aliasing (GCC) 等警告 因此比較好的寫法應該會是: #define var_sp(x) _Generic((x), char: "%s%c\n", int: "%s%d\n") #define prompt(x) _Generic((x), char: "char = ", int: "num = ") int main (void) { char c = 'a'; int n = 10; printf(var_sp(c), prompt(c), c); printf(var_sp(n), prompt(n), n); } ※ 引述《rice9547 (一碗飯)》之銘言: : : 預期的正確結果(Expected Output): : line 13, 14 輸出正確 : line 16卻輸出 error : 預期應該會和 line 13一樣 : : 程式碼(Code):(請善用置底文網頁, 記得排版) : https://ideone.com/1FaCEr -- ※ 發信站: 批踢踢實業坊(ptt.cc), 來自: 140.113.68.52 ※ 文章網址: https://www.ptt.cc/bbs/C_and_CPP/M.1510795456.A.761.html
james732: 完全不知道有這東西,感謝 11/16 10:55
peterwu4: 好厲害,推一個~ 11/16 12:59
ilikekotomi: 推 感謝分享 11/16 20:01
被m起來惹嗚 >///<
wtchen: 已經躺進精華區囉 11/16 20:57
sppmg: 好文,一直對 _Generic 感興趣。不過 tcc 不支援的樣子... 11/16 22:32
Lipraxde: 要怎麼樣才能厲害到要出什麼警告都知道啊? 11/16 22:58
Clang 那個是編譯了才知道的 XD ※ 編輯: Hazukashiine (122.116.185.23), 11/18/2017 11:39:06
hunandy14: 凄い~勉強になりました~ 11/20 12:25