MISRA C-2012规则11.3违规,同时尝试从char到int指针进行类型转换

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.

Lun*_*din 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位系统上的隐式升级所必需的,此外,您永远不应对签名类型进行位移.

  • @Lundin"它是一个(合格的)类型与对象的有效类型兼容吗?" 是的,如果原始指针指向`int32_t`变量.你不能说`do_test`总是展示UB,如果它不总是这样做的话.假设OP没有传递一个指向`int32_t`变量的指针,*但是这个假设没有在问题中明确说明* - OP的问题中没有调用该函数的代码. (2认同)