【问题标题】:Does each branch of c11 _Generic generic association's result expressions have to be valid?c11 _Generic 泛型关联的结果表达式的每个分支都必须有效吗?
【发布时间】:2015-03-20 06:55:42
【问题描述】:

我似乎无法将参数传递给期望不同参数的函数(或其他实现第一个类型子集的 _Generic 宏)。

#define DEBUG_PRINT(x,...) _Generic((x),                    \
    debug_print_options *: DEBUG_PRINT_CUSTOM_TYPE(x,  __VA_ARGS__),    \
    default: DEBUG_PRINT_BASIC_TYPE(x, __VA_ARGS__))


#define DEBUG_PRINT_BASIC_TYPE(x,...) debug_print_printf_specifier((#x), (x), TYPE_TO_PRINTF_SPECIFIER(x), __FILE__, __LINE__, _my_func__, &((struct debug_print_options){__VA_ARGS__}))
#define DEBUG_PRINT_CUSTOM_TYPE(x,...) debug_print_custom_to_debug_string((#x), (x), GET_CREATE_DEBUG_STRING_FUNC(x), __FILE__, __LINE__, _my_func__, &((struct debug_print_options){__VA_ARGS__}))

给出编译错误:

debug_print.h:123:46: error: ‘_Generic’ selector of type ‘struct debug_print_options *’ is not compatible with any association

这使它看起来好像在每个分支机构都得到了评估。如果我注释掉它编译的默认值。

有没有办法解决这个问题?

【问题讨论】:

  • 另外,如果每个分支都被评估,为什么???
  • Incompatible pointer types passing in _Generic macro 的可能重复项,并回答您的“为什么”问题:如果您有类似 if(0) something; else other; 的内容,这也是一样的,所有分支也必须有效。将其视为一项功能,可能所有分支都可能在某些平台上处于活动状态,因此最好从语法上检查它们。

标签: c interface c11


【解决方案1】:

您的编译器错误不是来自宏本身,而是来自对它们的某些调用。因此,如果您发布导致错误的调用会有所帮助。话虽如此,我将解决您关于 _Generic 表达式的一般性问题。

标准规定如下(6.5.1.1,在“语义”下):

不评估通用选择的控制表达式。如果一个通用选择 具有与类型名称兼容的泛型关联 控制表达式,则泛型选择的结果表达式是 该通用关联中的表达式。否则,泛型的结果表达式 selection 是默认通用关联中的表达式。没有任何表达 评估来自任何其他通用关联的通用选择。

因此,在回答您的评论时添加您的问题,不,只评估选定的分支。

_通用表达式是表达式,而不是宏。宏不需要具有正确的语法。它甚至不需要括号平衡。宏需要做的唯一想法是在每次使用时扩展为有效代码。表达方式不同。它们需要匹配语言的语法。

在 _Generic 表达式的情况下,每个项目的语法可以是任何有效的 C 表达式,该表达式不具有未被括号(或条件运算符)屏蔽的逗号运算符。如果您的 _Generic 符合此条件,并且所选语句不会导致问题,那么它将起作用。因此,只要语法有效,它就会起作用。

当您不知道变量的类型时,使用正确的语法可能有点棘手。如果您对此有疑问,您可以在需要时在“x”上插入显式强制转换,将其强制转换为该分支上的类型。这样代码是有效的,并且强制转换是多余的并且会被优化掉。

至于您遇到的特定错误,听起来就像您没有与您的输入匹配的类型并且您没有默认语句时遇到的错误。再一次,没有看到你的调用,很难说。但我会确保你匹配的类型完全包括限定符。我要问的一个特殊问题是 debug_print_options 是否是 typedef,就好像它只被定义为结构标记一样,那么您需要在 _Generic 中放入“struct”以正确识别类型。

【讨论】:

  • 为简单起见,它是 typedef。我最终选择了 void * 并返回以满足所有分支:github.com/rtaycher/debug_print_h/blob/master/debug_print.h
  • 好吧,如果没有看到导致问题的宏的调用,就很难说问题出在哪里。宏基本上是一个缩写,用于回答实际代码需要给出的问题,而不仅仅是缩写规则而不看它是如何使用的。
猜你喜欢
  • 2023-03-12
  • 2013-04-25
  • 1970-01-01
  • 1970-01-01
  • 2018-03-27
  • 2018-11-20
  • 1970-01-01
  • 2016-08-25
  • 1970-01-01
相关资源
最近更新 更多