(首先请注意,我知道在运行时确定字节顺序并不是一个理想的解决方案,并且有更好的想法。请不要提出这个问题)
我需要在运行时检查我的CPU的字节顺序。我还必须在保持MISRA兼容的同时这样做。我正在使用C99。
MISRA不允许在不同类型的指针之间进行转换,因此只需将uint32_t*
转换为uint8_t*
并取消引用以查看uint8_t
所持有的值是不允许的。使用union
s也是不可能的(MISRA不允许使用union
s)。
我也尝试在下面的代码中使用memcmp
:
static endi get_endianess(void)
{
uint32_t a = 1U;
uint8_t b = 1U;
return memcmp(&a, &b, 1) == 0 ? endi_little : endi_big;
}
但MISRA说,The pointer arguments to the Standard Library function 'memcmp' are not pointers to qualified or unqualified versions of compatible types
,意思是我没有通过转换为合法的void*
指针并让memcmp
做肮脏的工作来超越它。
任何其他聪明的想法将不胜感激。如果您没有MISRA检查员,请将您的想法发给我,我会告诉您我的检查员所说的内容
我认为你误解了MISRA-C规则。像这样的代码很好:
uint16_t u16 = 0xAABBu;
bool big_endian = *(uint8_t*)&u16 == 0xAAu;
MISRA-C:2012规则11.3有一个例外,允许指针转换指向字符类型(uint8_t
可以安全地被视为),但不是相反。规则的目的是防止错位访问和严格别名错误。
此外,MISRA允许union
就好了,反对它的规则是建议性的,只是为了迫使人们停下来思考他们如何使用工会。 MISRA不允许union
在同一存储区域中存储多个不相关的东西,例如创建变体和其他类似的废话。但是,考虑到填充/对齐和结束的受控类型双关语可以与MISRA一起使用。也就是说,如果你不喜欢这个顾问规则。我个人总是在我的MISRA实现中忽略它。
在MISRA上下文中,我认为此标头和此函数可能不可用,但是:
#include <arpa/inet.h>
static endi get_endianness(void)
{
return htons(0x0001u) == 0x0001u ? endi_big : endi_little;
}