繁体   English   中英

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

[英]MISRA C-2012 Rule 11.3 violation while trying to do a typecast from char to int pointer

我试图从我的代码中摆脱规则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,有符号char或无符号char之一的指针。 该标准保证可以使用指向这些类型的指针来访问对象的各个字节。

由于char类型,请忽略Dir 4.6。

您很幸运,您正在使用MISRA-C,因为此代码充满了错误。 您无法通过强制转换使错误消失。

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

    指向对象类型的指针可以转换为指向不同对象类型的指针。 如果结果指针未针对引用类型正确对齐,则该行为未定义。

  • 错误2。该代码包含公然的严格别名冲突。 根据C标准6.5 / 7,这始终是未定义的行为。

    您的假设“标准保证了可以使用指向这些类型的指针来访问对象的各个字节。” 是正确的:作为特殊的例外,C允许您从x指针转换为char指针,然后通过char指针访问数据。 但是并非相反

    您的代码访问单个字节; 从字符数组到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]);
}

此移位版本始终是首选,因为它与流行病无关,因此可移植。 必须进行强制转换为uint32_t才能防止在8/16位系统上进行隐式提升,此外,绝对不应对有符号类型进行移位。

如果您需要避免显式强制转换,则可以随时执行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;一样有效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];
}

原始代码可能会导致不确定的行为:

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

如果int32_t在平台上具有对齐要求,并且cp未针对该要求正确对齐,则该行为未定义。

我一般都不喜欢MISRA,但是这种特殊情况似乎是合理的。 即使您碰巧在没有对齐要求的平台上(即使在嵌入式开发中也不可能),该代码也是不可移植的,如果您移至具有对齐要求的CPU,它可能会开始中断。

一个好的解决方案是使用定义明确的memcpy代替:

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM