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

jw5wzhpr  于 2023-01-12  发布在  其他
关注(0)|答案(3)|浏览(259)

我正试图从我的代码中删除规则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;
}

我希望 *c和 *x的值相同,即使代码正在编译并给出正确的值,“x =(int32_t *)cp;“导致违反11.3和11.8
违反规则11.3:具有指针类型的对象不应转换为指向不同对象类型的指针。
我尝试过使用void指针,但结果与我预期的不一样,而且还导致了额外的违规。
有办法消除这些违规行为吗?
在MISRA C 2012文档中,他们提到该规则有一个例外,因为允许将指向对象类型的指针转换为指向对象类型char、signed char或unsigned char之一的指针。该标准保证指向这些类型的指针可用于访问对象的单个字节。
由于字符类型,忽略Dir 4.6。

uxhixvfz

uxhixvfz1#

你很幸运你使用的是MISRA-C,因为这段代码充满了bug,你不能用强制类型转换来消除bug。

  • 错误1。字符指针不一定对齐,在这种情况下,您的代码会根据C标准www.example.com调用未定义的行为6.3.2.3/7:

指向一个对象类型的指针可以转换为指向另一个对象类型的指针。如果结果指针没有与引用类型正确对齐,则该行为未定义。

  • 错误2:代码中包含了一个明显的严格别名违规。根据C标准6.5/7,这总是未定义的行为。

您的假设“标准保证指向这些类型的指针可以用于访问对象的各个字节。”是正确的:作为一个特殊的例外,C允许你从指向x的指针转换为指向char的指针,然后通过char指针访问数据。
您的代码 * 不 * 访问单个字节;你正在走另一条路,从一个字符数组到一个32位类型。这是不允许的。参见What is the strict aliasing rule?
正确的代码,这应该是确定与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])        );
}

这种移位版本总是首选的,因为它与字节序无关,因此可移植。强制转换为uint32_t对于防止8/16位系统上的隐式提升是必要的,而且您永远不应该对有符号类型进行移位。

szqfcxe2

szqfcxe22#

如果您觉得有必要避免显式强制转换,您总是可以执行memcpy

#include <string.h>
#include <stdint.h>

static int32_t 
do_test(const char *cp)
{
    int32_t r;
    memcpy(&r,cp,sizeof(r));
    return r;
}

使用内置mempcy的优化编译器,这应该与return *(int32_t*)cp;(您的代码,编写得更简洁)一样高效。
请记住,在任何一种情况下,仅当传入的cp值指向有效的int32_t对象时,才定义代码。
如果memcpy因为char*void*的隐式转换而不能正常工作,您可以将其替换为定制的普通实现的void charwise_memcpy(char *Dest, char const *Src, size_t Sz);或等效的for循环。

void charwise_memcpy(char *Dest, char const *Src, size_t Sz)
{
    for(size_t i=0; i<Sz; i++)
        Dest[i]=Src[i];
}
3mpgtkmj

3mpgtkmj3#

原始代码可能导致未定义的行为:

const char *cp;
// ...
x = (const int32_t *)cp;

如果int32_t在平台上有对齐要求,而cp没有针对该要求正确对齐,则行为是未定义的。
一般来说,我不是MISRA的粉丝,但是这个例子看起来很合理。即使你碰巧在一个没有对齐要求的平台上(即使在嵌入式开发中也不太可能),这个代码也是不可移植的,如果你转移到一个有对齐要求的CPU上,它可能会开始崩溃。
一个好的解决方案是使用定义良好的memcpy

相关问题