联合不能在类型说明符中定义

时间:2019-08-27 17:36:30

标签: c++ c++11

我尝试在我的C ++应用程序中包含来自Github的c代码库,但是遇到一些编译错误。

原始代码错误:

'_u16' cannot be defined in a type specifier


non-constant-expression cannot be narrowed from type 'int' to 'uint8_t' (aka 'unsigned char') in initializer list [-Wc++11-narrowing]

应用程序是在MacOS上使用CMake由Clang 10.0.1编译的,其中包含CMakeLists.txt:

set(CMAKE_C_STANDARD 11)
set(CMAKE_C_STANDARD_REQUIRED ON)
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -std=c11")

set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")

以下是原始代码:

inline static void UInt16SetBE(void *b2, uint16_t u)
{
    *(union _u16 { uint8_t u8[16/8]; } *)b2 = (union _u16) { (u >> 8) & 0xff, u & 0xff };
}

以下是我添加强制转换以解决错误后的代码:

inline static void UInt16SetBE(void *b2, uint16_t u)
{
    *(union _u16 { uint8_t u8[16/8]; } *)b2 = (union _u16) { (uint8_t)((u >> 8) & 0xff), (uint8_t)(u & 0xff) };
}

更改后出现错误:

'_u16' cannot be defined in a type specifier

有人知道声明的语法是什么意思吗? *(union _u16 { uint8_t u8[16/8]; } *)b2

2 个答案:

答案 0 :(得分:3)

他们声明一个联合类型_u16,其中包含两个字节的数组,然后他们假装指针b2是该类型联合的指针。然后,它们取u并取其高字节和低字节,并将它们分别分配给该数组的两个位置。设置大端16位值是一种相当混乱的方式。

您尝试解决编译错误的方向是正确的,但是要使其与Clang一起使用,我认为您需要先声明并集类型,以便编译器在赋值的右侧识别它。

inline static void UInt16SetBE(void *b2, uint16_t u)
{
    union _u16 { uint8_t u8[16/8]; };
    *(union _u16 *)b2 = (union _u16) { (uint8_t)((u >> 8) & 0xff), (uint8_t)(u & 0xff) };
}

也就是说,该代码非常令人困惑,并且有更简单的方法可以做到这一点,例如:

inline static void UInt16SetBE(void *b2, uint16_t u)
{
    ((uint8_t *) b2)[0] = (uint8_t) (u >> 8) & 0xff;
    ((uint8_t *) b2)[1] = (uint8_t) u & 0xff;
}

答案 1 :(得分:3)

在C语言中,表达式

*(union _u16 { uint8_t u8[16/8]; } *)b2

使用标签_u16定义一个并集,将b2强制转换为该新定义的并集类型的指针,然后取消对该指针的引用。但是,在C ++中,以这种方式尝试在类型转换中定义类或联合类型是无效的语法。我们可以通过以下定义来解决此问题:

union _u16 { uint8_t u8[16/8]; };
*(union _u16*)b2 = (union _u16) { (u >> 8) & 0xff, u & 0xff };