在学习宏的工作原理时,我尝试定义一个适用于不同数据类型的宏,而不必定义多种类型。我曾经_Generic
让这项任务变得更容易。然而,在多次更改后,它仍然不起作用,于是我让 deepseek 来解决这个问题,最终我得到了这个:
#define FOO(var) _Generic((var), \
int: printf(#var " = %d\n", (int)(var)), \
double: printf(#var " = %lf\n", (double)(var)), \
long: printf(#var " = %ld\n", (long)(var)), \
char: printf(#var " = '%c'\n", (char)(var)), \
float: printf(#var " = %f\n", (float)(var)), \
default:printf(#var " = unknown type\n"))
int main(void) {
int a = 3;
FOO(a); // correctly prints "a = 3"
}
在 cpp-reference 和 SO 中的其他代码示例中,我从未见过有人必须进行类型转换才能使其工作。删除类型转换 (... int: printf(#var " = %d\n",(var)), \
...) 会显示警告“格式指定类型 'long' 但参数类型为 'int'”,并给出编译警告(-Wall
已启用):
ue_05.c: In function ‘main’:
ue_05.c:47:14: warning: format ‘%lf’ expects argument of type ‘double’, but argument 2 has type ‘int’ [-Wformat=]
47 | FOO(a);
| ^
ue_05.c:27:25: note: in definition of macro ‘FOO’
27 | double: printf(#var " = %lf\n", (var)), \
| ^~~
ue_05.c:47:14: warning: format ‘%ld’ expects argument of type ‘long int’, but argument 2 has type ‘int’ [-Wformat=]
47 | FOO(a);
| ^
ue_05.c:28:25: note: in definition of macro ‘FOO’
28 | long: printf(#var " = %ld\n", (var)), \
| ^~~
ue_05.c:47:14: warning: format ‘%f’ expects argument of type ‘double’, but argument 2 has type ‘int’ [-Wformat=]
47 | FOO(a);
| ^
ue_05.c:30:25: note: in definition of macro ‘FOO’
30 | float: printf(#var " = %f\n", (var)), \
我一直没能找出为什么这里需要类型转换并且 deepseek 也没能解释清楚。
为什么这里需要类型转换以及它在哪里被记录下来?
只需
#define
编辑代码即可。当你写的时候
预处理完成后,它就变成了幕后工作
什么时候
a
编译int
器仍然会看到以及其他语句。因此,即使该语句不会被执行,也会向您发出警告,抱怨变量
a
正在期望int
中。printf
float
类型转换只是让编译器将其视为
a
(float
在float:
的部分中_Generic
,在其余部分中依此类推),因此不会对此提出抱怨。顺便说一下,你可能已经开启
-Wall
了。编辑:
要消除警告,请执行以下操作