解释`_Generic`错误消息:错误:一元'*''的无效类型参数(有'`int`')

时间:2015-09-18 01:58:23

标签: c generics gcc clang c11

我通常不需要帮助理解错误消息,但是这个似乎一定是个bug。我已经梳理了“可能已经有你答案的问题”,但这些问题似乎都没有使用C11最新增加的_Generic功能,所以我认为这可能是一个独特的问题。这是我的测试用例:

#include <stdio.h>
#define foo(bar) _Generic((bar), int:   sizeof (bar)   \
                               , int *: sizeof *(bar))

int main(void) {
    printf("%d\n", foo(42));
}

我在gcc 5.2中看到的错误消息是:

  

错误:一元“*”的无效类型参数(包含“int”)

     

注意:扩展宏“foo

clang发出类似意义的消息:

  

致命错误:间接需要指针操作数('int'无效)

     

注意:从宏“foo

扩展

这些消息似乎意味着以下之一:

  • 编译器选择了int *泛型关联中的表达式。
  • 对通用关联的表达式进行了评估。

C11§6.5.1.1p3似乎明确禁止这两种解释:

  

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

有人可以为我提供一些关于此错误消息的信息吗?

1 个答案:

答案 0 :(得分:2)

编译器是正确的:sizeof *(42)是一种约束违规,因为它将*应用于整数类型的表达式。现在_Generic的一件事很重要,要知道,这不是处理预处理时间,而是作为C语言意义上的正确表达式(具有最高优先级)。这个_Generic表达式的效果实际上和做

之类的效果相同
(1 ? sizeof (42) : sizeof *(42))

在这里你知道永远不会评估第二个分支,但是没有人希望这个可以编译。