Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/svg/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何编写完全兼容MISRA:2012的memcpy函数?_C_Void Pointers_Misra_Qualifiers - Fatal编程技术网

如何编写完全兼容MISRA:2012的memcpy函数?

如何编写完全兼容MISRA:2012的memcpy函数?,c,void-pointers,misra,qualifiers,C,Void Pointers,Misra,Qualifiers,我编写了这个memcpy函数,但我仍然需要禁用规则11.5和11.8。是否有完全兼容MISRA:2012的解决方案 #pragma cstat_suppress="MISRAC2012-Rule-21.6" // Uses of stdio.h were found. #include <stdio.h> #include <stdint.h> #include <string.h> #include <stdlib.h> extern int

我编写了这个
memcpy
函数,但我仍然需要禁用规则11.5和11.8。是否有完全兼容MISRA:2012的解决方案

#pragma cstat_suppress="MISRAC2012-Rule-21.6" // Uses of stdio.h were found.
#include <stdio.h>

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

extern int main(void);

static int_least8_t _memcpy(void *dst, const void *src, const size_t length)
{
    #pragma cstat_disable="MISRAC2012-Rule-11.5" // A conversion from a pointer to void into a pointer to object was found.
    int_least8_t* destination = (int_least8_t*)dst;
    #pragma cstat_disable="MISRAC2012-Rule-11.8" // A cast that removes a const or volatile qualification was found.
    const int_least8_t* source = (int_least8_t*)src;
    #pragma cstat_restore="MISRAC2012-Rule-11.5","MISRAC2012-Rule-11.8"

    for (size_t i = 0; i < (length / sizeof(int_least8_t)); i++)
    {
        destination[i] = source[i];
    }
    return 0;
}

int main(void)
{
    int32_t src[32];
    int32_t dst[32];

    (void)memset(src, 0xff, sizeof(src));

    (void)_memcpy(dst, src, 128);

    for (size_t i = 0; i < (sizeof(src) / sizeof(src[0])); i++)
    {
        (void)printf("%d <=> %d\n", src[i], dst[i]);
    }

    return 0;
}
找到stdio.h的用法。 #包括 #包括 #包括 #包括 外部内部主(无效); 静态内部最小8个内存(无效*dst,常量无效*src,常量大小长度) { #pragma cstat_disable=“MISRAC2012-Rule-11.5”//找到从指向void的指针到指向对象的指针的转换。 int_least8_t*目的地=(int_least8_t*)dst; #pragma cstat_disable=“MISRAC2012-Rule-11.8”//A找到删除常量或volatile限定的强制转换。 const int_least8_t*源=(int_least8_t*)src; #pragma cstat_restore=“MISRAC2012-Rule-11.5”、“MISRAC2012-Rule-11.8” 对于(大小i=0;i<(长度/大小f(至少8);i++) { 目的地[i]=源[i]; } 返回0; } 内部主(空) { int32_t src[32]; int32_t dst[32]; (void)memset(src,0xff,sizeof(src)); (无效)_memcpy(dst,src,128); 对于(size_t i=0;i<(sizeof(src)/sizeof(src[0]);i++) { (无效)printf(“%d%d\n”,src[i],dst[i]); } 返回0; }
我使用IAR作为编译器,使用C-STAT进行静态分析

您无法使用标准格式编写
memcpy
,并且完全符合MISRA。正如您所注意到的,MISRA不允许
restrict
。但也有规则11.5

关于从指针到void再到指针到类型的强制转换的规则11.5在实践中太麻烦了。这是一条建议性的规则,所以我将跳过它。您不需要提出偏差

然而,关于淘汰资格赛的规则11.8是合理的(并且是必需的)。在这种情况下,没有理由这样做。您的代码中有一个由MISRA阻止的错误。将代码更改为

const int_least8_t* source = (const int_least8_t*) src;

补充说明:

  • 您不需要向
    main()
    提供转发声明
  • MISRA-C不允许使用stdio.h
  • 避免声明以下划线开头的标识符,请参阅C11 7.1.3
  • 在这里使用
    int\u least8\t
    没有明显的好处。此外,有符号类型也有问题。我会用
    uint8\t
    来代替

你能给我们解释一下规则11.5和11.8吗,这样我们就不必去查了?如果你把这个问题表述为一个编程问题,你会得到更多的帮助。@Joe完成了,但在上一个MISRA修正案中有一些有趣的东西:。似乎memcpy是一个特殊的case@nowox这项修正案并不特别有趣,有人又一次在严格的别名规则中挖得太深了
memcpy
没有类型安全性,就是这样。此外,
memcpy
本身在确定对象的有效类型方面起着作用。但另一条规则的理由并不充分。无论如何,您的代码不是标准库
memcpy
,因此该规则不适用。以下划线开头的名称保留用于实现。应用程序代码不能使用它们。作为旁注:我为什么不使用标准库的
memcpy
,它很可能是高度优化的,但是一些自制的、速度最慢的版本?为什么
\u memcpy
返回0?这对于任何希望它像标准的
memcpy()
一样工作的人来说都是一个惊喜。而且绝对没有必要像这样抛弃常量:
const int\u least8\u t*source=(const int\u least8\u t*)src应该可以。使用
int\u least8\t
也可能存在对齐问题。无法保证要复制的内存与类型对齐。我会说使用
无符号字符
,因为在任何情况下它都可能与
uin8\u t
不同,那么
使用无符号字符
将是正确的答案。@Persixty MISRA-C鼓励使用
stdint.h
,如果不使用stdint类型,你需要一个好的理由。这不是一个很好的理由-如果您的系统不支持
uint8\t
,但有16位字符,那么您的DSP功能就不正常了。你应该用汇编语言而不是C语言来编写。对于普通的C语言程序来说,绝对没有必要为那些古怪的、异国情调的、过时的DSP提供可移植性。这样做的人只是在浪费每个人的时间。为现实世界的主流计算机架构提供可移植性就足够了。我没有意识到这一点。我同意这是一个疯狂的理论,在汽车行业的某个地方,有人使用的不是8位字节的东西(但我在此不把它超过雷诺或菲亚特)。面对这条(坦率地说是严厉的)规则,我没有什么好的理由。但对齐点仍然存在。将
void*
强制转换为对齐类型还有一个问题您没有标记。@将任何
uint8\t
(或字符类型)复制到同一类型的另一个变量完全可以。当您尝试以其他类型访问指向的数据时,会出现对齐问题,在这种情况下,您也会遇到严格的别名问题,这是MISRA不允许的。不管怎么说,不一致本身并不是“my_memcpy”的问题,而是调用者的问题。除此之外,基于对齐字长的拷贝会在某些系统上产生更快的代码,而不是逐字节。
uint\u fast8\t
可能需要解决对齐问题
uint\u fast8\t
是最快的类型,至少有8位。可能更宽,并在优化平台上对齐。它最有可能使用对齐的指令——因为它的广告发布速度一样快!您可以编写
my\u memcpy()
来执行第一个奇数字节作为
uint8\u t
,正文作为更宽的类型,最后一个字节作为
uint8\u t