C11_Generic将true和false推断为整数

Mat*_*son 6 c generics c11

在C11中,有一个_Generic宏可以允许很酷的通用功能.但是,在正常情况下使用true和false使用此结果会导致错误的扣除:

#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));
}
Run Code Online (Sandbox Code Playgroud)

这打印:

1: int
true: bool
false: bool
Run Code Online (Sandbox Code Playgroud)

但是没有中间位重新定义true和false:

1: int
true: int
false: int
Run Code Online (Sandbox Code Playgroud)

这意味着您无法执行以下_Generic功能:

struct Variant * const int32 = variant_create(1);
struct Variant * const boolean = variant_create(true);
Run Code Online (Sandbox Code Playgroud)

所以我的问题是:

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

250*_*501 8

这两种类型都是宏:

7.18布尔类型和值

  1. 其余三个宏适用于#if预处理指令.
    它们是:
    true,扩展为整数常量1,
    false,扩展为整数常量0,
    和
    __bool_true_false_are_defined,扩展为整数常量1.

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

  1. 尽管有7.1.3的规定,程序可能会取消定义,然后重新定义宏bool,true和false.259)

    259)参见"未来图书馆方向"(7.31.9)

尽管引用了规则:

7.1.3保留标识符

  1. 如果程序删除(使用#undef)上面列出的第一个组中的标识符的任何宏定义,则行为是未定义的.

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

7.31.9布尔类型和值

  1. 取消定义,然后重新定义宏bool,true和false的能力是一个过时的功能.

所以我建议你创建自己的my_true和my_false宏,这些宏被转换为_Bool.