"error: ‘_Generic’ specifies two compatible types" but not on some compilers
"error: ‘_Generic’ specifies two compatible types" but not on some compilers
我有一个适用于 IAR 编译器的(复杂)代码。
我使用了该代码的一部分来制作一个片段来改进它。
但是在在线编译器上移动这段代码的一部分时,它无法编译。
"error: ‘_Generic’ specifies two compatible types"
因为我在这个例子中使用了 _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 上编译?
(是的,我要你相信我没有可复制的工作示例,因为我不会提供我的专有代码)
编辑:
在 godbolt:
- x86-64 clang 10 ,: 该代码仅适用于 c++!在 C 中产生类似的错误:
"type 'someEnum1_e*' in generic association compatible with previously specified type 'uint32_t *' (aka 'unsigned int *')"
- ARM64 GCC 8.2,标志 -std=c11:代码产生错误
- x64 GCC 9.3,标志 -std=c11:代码产生错误
- AVR GCC 5.4,标志 -std=c11:代码不识别 _Generic,也不识别 _Bool:
"error: '_Generic' was not declared in this scope"
- MSP430 GCC 6.2.1,标志 -std=c11:代码有效! (但不是在 C++ 中)
- 在我的 IAR 8.20.2 计算机上,标记 -std=c11:代码有效!
第一个奖励问题:这可能是编译器错误吗?标准是怎么说的?
第二个红利问题:有没有办法避免这个错误? (对于所有编译器)
测试我的说法的一小段
#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;};
}
我找到了一种编译方法,并且 运行 使用 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 提供的宏技巧。
我有一个适用于 IAR 编译器的(复杂)代码。 我使用了该代码的一部分来制作一个片段来改进它。 但是在在线编译器上移动这段代码的一部分时,它无法编译。
"error: ‘_Generic’ specifies two compatible types"
因为我在这个例子中使用了 _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 上编译?
(是的,我要你相信我没有可复制的工作示例,因为我不会提供我的专有代码)
编辑: 在 godbolt:
- x86-64 clang 10 ,: 该代码仅适用于 c++!在 C 中产生类似的错误:
"type 'someEnum1_e*' in generic association compatible with previously specified type 'uint32_t *' (aka 'unsigned int *')"
- ARM64 GCC 8.2,标志 -std=c11:代码产生错误
- x64 GCC 9.3,标志 -std=c11:代码产生错误
- AVR GCC 5.4,标志 -std=c11:代码不识别 _Generic,也不识别 _Bool:
"error: '_Generic' was not declared in this scope"
- MSP430 GCC 6.2.1,标志 -std=c11:代码有效! (但不是在 C++ 中)
- 在我的 IAR 8.20.2 计算机上,标记 -std=c11:代码有效!
第一个奖励问题:这可能是编译器错误吗?标准是怎么说的?
第二个红利问题:有没有办法避免这个错误? (对于所有编译器)
测试我的说法的一小段
#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;};
}
我找到了一种编译方法,并且 运行 使用 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 提供的宏技巧。