首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >将_Generic与其他宏结合起来

将_Generic与其他宏结合起来
EN

Stack Overflow用户
提问于 2020-10-13 19:13:59
回答 2查看 126关注 0票数 1

因此,我熟悉嵌套宏。现在,我想用其他宏(如:

代码语言:javascript
运行
复制
#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;
}

但它正在引发一个错误,因为

代码语言:javascript
运行
复制
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)
      |       ^~~~~~~~~~~~~~
EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2020-10-13 21:56:14

重要的是要理解,虽然泛型选择除了与宏一起使用之外并不真正有用,但它本身并不是由预处理器来解释的。那么,考虑一下这一声明:

some_func("hello");

在示例代码中,将some_func定义为类似函数的宏的标识符,在重新扫描之前,该宏的扩展将产生此结果:

代码语言:javascript
运行
复制
_Generic(("hello"), char *: some_func_char, default: some_func_default)("hello")

然后,预处理器扫描该宏以寻找进一步的宏替换,但同样,_Generic不是宏,它对预处理器没有其他特殊意义。有一个some_func_char的作用域内定义作为类似函数的宏的标识符,但是该标识符在上面的行中的外观与它不匹配,因为它后面没有一个开括号。行中的其他内容对预处理程序也没有任何意义(在上下文中),因此这实际上是最终的预处理形式。

现在,请注意表达式("hello")与泛型选择表达式的char *选项相匹配,因此函数标识符some_func_char是选定的结果,但是括号大小的参数列表("hello")不包含该函数的正确参数数。在尝试调用(some_func_char)("hello")时,整体表达式是一个更复杂的变体。some_func_char()宏从未发挥作用。

现在应该很清楚,您不能使用泛型选择来选择使用不同数量参数的函数的函数标识符。当然,您可以使用它来选择不同的函数调用。例如,

代码语言:javascript
运行
复制
#define some_func(X) _Generic(                \
    (X),                                      \
    char *:  some_func_char((X), sizeof (X)), \
    default: some_func_default(X)             \
)

void some_func_char(char *s, size_t z) { }
void some_func_default(void *p) { }

int main(void) {
    some_func("hello");
}
票数 1
EN

Stack Overflow用户

发布于 2020-10-13 19:34:44

some_func_char正在调用函数而不是_Generic调用中的宏(甚至试图用括号停止展开),另一方面,如果some_func_char需要两个参数,则不能在some_func_default中省略第二个参数,切换到:

代码语言:javascript
运行
复制
#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;
}

或者更好的是:

代码语言:javascript
运行
复制
#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非常快。

另外,请注意,sizeof(char)总是1

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/64341753

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档