因此,我熟悉嵌套宏。 现在,我想更改一个由_Generic首先更改的宏以及其他一些宏,例如:
#include<stdio.h>
#define some_func(X) _Generic((X), \
char* : some_func_char, \
default : some_func_default)(X)
#define some_func_char(X) some_func_char(X, sizeof(X)/ sizeof(char))
void (some_func_char)(char *blah, size_t len_blah)
{
// do something
}
void some_func_default(double blah)
{
// code
}
int main()
{
some_func("hello");
return 0;
}
但它正在引发错误
main.c: In function ‘main’:
main.c:5:22: error: too few arguments to function ‘some_func_char’
5 | #define some_func(X) _Generic((X), \
| ^~~~~~~~
main.c:22:3: note: in expansion of macro ‘some_func’
22 | some_func("hello");
| ^~~~~~~~~
main.c:10:7: note: declared here
10 | void (some_func_char)(char *blah, size_t len_blah)
| ^~~~~~~~~~~~~~
答案 0 :(得分:2)
some_func_char
在_Generic
调用中正在调用函数而不是宏(即使试图用括号停止扩展),另一方面,您不能省略{{ 1}}如果some_func_default
需要两个参数,请切换到:
some_func_char
或更妙的是:
#include <stdio.h>
#define some_func(X) _Generic((X), \
char *: some_func_char, \
default: some_func_default)(X, sizeof X)
void some_func_char(char *blah, size_t len_blah)
{
// do something
}
void some_func_default(double blah, size_t dummy)
{
(void)dummy;
// code
}
int main()
{
some_func("hello");
return 0;
}
第二个版本允许您也为指向#include <stdio.h>
#include <string.h>
#define some_func(X) _Generic((X), \
char *: some_func_char, \
default: some_func_default)(X)
void some_func_char(char *blah)
{
size_t len = strlen(blah);
// do something
}
void some_func_default(double blah)
{
// code
}
int main()
{
some_func("hello");
return 0;
}
的指针传递并计算正确的长度,不用担心性能,char
非常快。
还要注意,strlen
始终为1
答案 1 :(得分:1)
重要的是要理解,尽管泛型选择除与宏结合使用外并没有真正的用处,但预处理器本身并不能解释泛型选择。然后考虑以下语句:
some_func("hello");
在示例代码中出现的地方,定义了some_func
作为类函数宏的标识符,并且在重新扫描之前,该宏的扩展会产生该定义:
_Generic(("hello"), char *: some_func_char, default: some_func_default)("hello")
然后,预处理器将扫描该宏以进行进一步的宏替换,但是_Generic
也不是宏,并且对预处理器没有其他特殊意义。在范围内定义some_func_char
作为类函数宏的标识符,但是该标识符在上一行中的外观与之不匹配,因为它后面没有括号。在上下文中,该行中的其他任何内容都不重要,因此实际上是最终的预处理形式。
现在观察到表达式("hello")
与通用选择表达式的char *
匹配,因此函数标识符some_func_char
是选择的结果,但括号参数列表{{1} }没有包含该函数的正确数量的参数。整体表达式是尝试调用("hello")
时的更复杂的变化。 (some_func_char)("hello")
宏永远不会起作用。
现在应该很清楚,您不能使用通用选择来选择带有不同数量参数的函数的函数标识符。但是您当然可以 使用它来选择不同的函数 calls 。例如,
some_func_char()