Re: [问题] void指标输出值问题

楼主: Hazukashiine (私は幸せです)   2017-11-16 09:24:13
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
作者: hunandy14 (Charlott.HonG)   2017-11-20 12:25:00
凄い~勉强になりました~
作者: james732 (好人超)   2017-11-16 10:55:00
完全不知道有这东西,感谢
作者: peterwu4 (notd)   2017-11-16 12:59:00
好厉害,推一个~
作者: ilikekotomi (Young)   2017-11-16 20:01:00
推 感谢分享
作者: wtchen (没有存在感的人)   2017-11-16 20:57:00
已经躺进精华区囉
作者: sppmg (sppmg)   2017-11-16 22:32:00
好文,一直对 _Generic 感兴趣。不过 tcc 不支援的样子...
作者: Lipraxde (Lipraxde)   2017-11-16 22:58:00
要怎么样才能厉害到要出什么警告都知道啊?

Links booklink

Contact Us: admin [ a t ] ucptt.com