Sal*_*lim 1 c pointers casting misra
我试图从我的代码中删除规则11.3.
示例代码:
static int32_t
do_test(const char *cp)
{
const char *c = cp;
const int32_t *x;
x = (const int32_t *)cp;
return *x;
}
Run Code Online (Sandbox Code Playgroud)
我希望*c和*x的值相同.即使代码正在编译并给出正确的值,"x =(int32_t*)cp;" 导致违反11.3和11.8
规则11.3违规:具有指针类型的对象不应转换为指向不同对象类型的指针.
我已尝试使用void指针,但结果与我的预期不一样,并且还导致了额外的违规.
反正有没有删除这些违规行为?
从MISRA C 2012文档中可以看出,这个规则有一个例外,因为它允许将指向对象类型的指针转换为指向对象类型char,signed char或unsigned char之一的指针.标准保证可以使用指向这些类型的指针来访问对象的各个字节.
由于char类型而忽略Dir 4.6.
你很幸运,你使用的是MISRA-C,因为这段代码充满了bug.你不能让一个错误消失.
错误1.字符指针不一定对齐,在这种情况下,您的代码根据C标准6.3.2.3/7调用未定义的行为:
指向对象类型的指针可以转换为指向不同对象类型的指针.如果生成的指针未针对引用的类型正确对齐,则行为未定义.
错误2.代码包含明显的严格别名违规.根据C标准6.5/7,这始终是未定义的行为.
您的假设"标准保证指向这些类型的指针可用于访问对象的各个字节." 是正确的:作为一个特殊的异常,C允许您将指针转换为指针指向char,然后通过char poiner访问数据.但不是相反.
您的代码不访问单个字节; 你会反过来,从一个字符数组到32位类型.这是不允许的.请参阅什么是严格别名规则?.
正确的代码,C语言和MISRA-C应该没问题:
static int32_t do_test(const char *cp)
{
return (int32_t) ((uint32_t)cp[0] << 24u) |
((uint32_t)cp[1] << 16u) |
((uint32_t)cp[2] << 8u) |
((uint32_t)cp[3]);
}
Run Code Online (Sandbox Code Playgroud)
这种移位版本总是首选,因为它与endianess无关,因此便于携带.转换为uint32_t防止8/16位系统上的隐式升级所必需的,此外,您永远不应对签名类型进行位移.
| 归档时间: |
|
| 查看次数: |
2888 次 |
| 最近记录: |