Re: [問題] void指標輸出值問題
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
推
11/16 10:55,
8年前
, 1F
11/16 10:55, 1F
推
11/16 12:59,
8年前
, 2F
11/16 12:59, 2F
推
11/16 20:01,
8年前
, 3F
11/16 20:01, 3F
被m起來惹嗚 >///<
推
11/16 20:57,
8年前
, 4F
11/16 20:57, 4F
推
11/16 22:32,
8年前
, 5F
11/16 22:32, 5F
推
11/16 22:58,
8年前
, 6F
11/16 22:58, 6F
Clang 那個是編譯了才知道的 XD
※ 編輯: Hazukashiine (122.116.185.23), 11/18/2017 11:39:06
→
11/20 12:25,
8年前
, 7F
11/20 12:25, 7F
討論串 (同標題文章)