首页 > 解决方案 > “错误:'_Generic' 指定了两种兼容的类型”,但在某些编译器上没有

问题描述

我有一个适用于 IAR 编译器的(复杂)代码。我使用了该代码的一部分来制作一个片段来改进它。但是在在线编译器上移动这段代码的一部分时,它不会编译。

“错误:'_Generic' 指定了两种兼容类型”

因为我使用 _Generic 作为这个例子:

#define  GET_TYPE_(data) _Generic((&data)+0, \
           _Bool * : TYPE_BOOL_, \
           uint8_t* : TYPE_U8_, \
           uint16_t* : TYPE_U16_, \
           uint32_t* : TYPE_U32_, \
           someEnum1_e* : TYPE_BOOL_, \
           someEnum2_e* : TYPE_SPECIAL_A, \
           someEnum3_e* : TYPE_SPECIAL_B, \
           default: TYPE_DEFAULT_ )

TYPE_XXX 是#define,那么我可以调用

switch(GET_TYPE_(myVariable))
{ 
case TYPE_XXXX: do_something(); break;
...
}

但是当我使用 gcc 在在线编译器(在线 gdb)上移动它时,我得到了错误:

error: ‘_Generic’ specifies two compatible types
   someEnum1_e* : TYPE_BOOL_, \
error: ‘_Generic’ specifies two compatible types
   someEnum2_e* : TYPE_SPECIAL_A, \
error: ‘_Generic’ specifies two compatible types
   someEnum3_e* : TYPE_SPECIAL_B, \

我读到这是一种正常行为,它不应该编译。但是,这怎么可能在 IAR 上编译呢?

(是的,我要求您在没有可重现的工作示例的情况下相信我,因为我不会提供我的专有代码)


编辑:在上帝螺栓上

第一个额外问题:可能是编译器错误吗?标准是怎么说的?

第二个奖金问题:有没有办法避免错误?(适用于所有编译器)

一个简短的片段来测试我的说法

#include <stdio.h>
#include <stddef.h>
#include <stdint.h>
#include <stdbool.h>
#include <string.h>
#include <stdarg.h>
#include <stdlib.h>

typedef enum
{
    ENUM1_A,
    ENUM1_B,
}someEnum1_e;

#define TYPE_E1_ 0
#define TYPE_U32_ 1

#define  GET_TYPE_(data) _Generic((&data)+0, \
           uint32_t* : TYPE_U32_, \
           someEnum1_e* : TYPE_E1_, \
           default: TYPE_U32_ )

int main (void)
{
    uint32_t foo;
    someEnum1_e bar;
    switch(GET_TYPE_(foo)){default:break;};
    switch(GET_TYPE_(bar)){default:break;};
}

标签: cgenericscompiler-errorsmacrosc11

解决方案


我找到了一种在 C11 中使用所有编译器编译和运行的方法(接受 _Generic 关键字):

#include <stdio.h>
#include <stddef.h>
#include <stdint.h>
#include <stdbool.h>
#include <string.h>
#include <stdarg.h>
#include <stdlib.h>

typedef enum
{
    ENUM1_A=0,
    ENUM1_B,
}someEnum1_e;


typedef union
{
    someEnum1_e value;
}someEnum1_e_t;


void print_uint32_t(uint32_t val)
{
    printf("uint32_t val = %u\n",val);
}

void print_someEnum1_e_t(someEnum1_e_t val)
{
    printf("someEnum1_e_t val = %u\n", val.value);
}

#define  PRINT_(data) _Generic((&data)+0, \
           uint32_t* : print_uint32_t((uint32_t)*((uint32_t*)&data)), \
           someEnum1_e_t* : print_someEnum1_e_t((someEnum1_e_t)*((someEnum1_e_t*)&data)), \
           default: printf("hello\n"))

int main (void)
{
    uint32_t       foo = 32;
    someEnum1_e_t  blah = {ENUM1_A};


    PRINT_(foo);
    PRINT_(blah);
}

要使此解决方案起作用,我不需要 Lundin 提供的宏技巧。


推荐阅读