C11_Generic 将 true 和 false 推导为整数

标签 c generics c11

在 C11 中,有一个 _Generic 宏可以实现很酷的泛型函数。然而,在正常情况下使用 truefalse 会导致不正确的推导:

#include <stdio.h>
#include <stdbool.h>

#define TypeName(x) \
  _Generic((x), \
    bool: "bool", \
    int: "int", \
    default: "unknown")

#if defined (__STDC_VERSION__) && (__STDC_VERSION__ >= 201112L) && (__bool_true_false_are_defined)
# undef true
# define true ((bool)(1))
# undef false
# define false ((bool)(0))
#endif

int main(void)
{
    printf("1: %s\n", TypeName(1));
    printf("true: %s\n", TypeName(true));
    printf("false: %s\n", TypeName(false));
}

这打印:

1: int
true: bool
false: bool

但是没有重新定义 truefalse 的中间位:

1: int
true: int
false: int

这意味着您不能执行 _Generic 函数,例如:

struct Variant * const int32 = variant_create(1);
struct Variant * const boolean = variant_create(true);

所以我的问题是:

  • 重新定义代码段是否安全?
  • 这是 C11 标准中的疏忽还是 GCC 和 Clang 中的错误?

最佳答案

这两种类型确实都是宏:

7.18 Boolean type and values

  1. The remaining three macros are suitable for use in #if preprocessing directives.
    They are:
    true which expands to the integer constant 1,
    false which expands to the integer constant 0,
    and
    __bool_true_false_are_defined which expands to the integer constant 1.

最后一条规则说你可以重新定义宏:

  1. Notwithstanding the provisions of 7.1.3, a program may undefine and perhaps then redefine the macros bool, true, and false. 259)

    259) See ‘‘future library directions’’ (7.31.9)

尽管引用了规则:

7.1.3 Reserved identifiers

  1. If the program removes (with #undef) any macro definition of an identifier in the first group listed above, the behavior is undefined.

规则 7.31.9 说重新定义可能不是一个好主意:

7.31.9 Boolean type and values

  1. The ability to undefine and perhaps then redefine the macros bool, true, and false is an obsolescent feature.

所以我建议您创建自己的 my_true 和 my_false 宏,它们被转换为 _Bool。

关于C11_Generic 将 true 和 false 推导为整数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27859715/

相关文章:

Java 类型参数不在其范围内

delphi - 使用继承的接口(interface)作为 TDictionary 中的键

java - 使用 GSON 反序列化嵌套的通用类时的奇怪行为

c - 错误 : use of undeclared identifier 'errno_t'

c - 原子结构的目的

c++ - libbpg-如何传递字节而不是文件路径

c - 比较 "if (arr<=arr1)"在给定程序中如何工作?

c - M_PI 不适用于 gcc --std=c11 但 --std=gnu11?

在 C 中创建一个动态变化的结构

c - 如何知道应用程序的启动点