我尝试在我的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
答案 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 };