Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/69.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
米斯拉在C_C_Pointers_Embedded_Misra - Fatal编程技术网

米斯拉在C

米斯拉在C,c,pointers,embedded,misra,C,Pointers,Embedded,Misra,在调试一些嵌入式代码时,我遇到了如下情况: buffPtr = &a[5]; buffEndPtr = &a[10]; while (buffPtr != buffEndPtr) { *buffPtr = 0xFF; buffPtr = &buffPtr[1]; /* MISRA improvement for: buffPtr++ */ } 为什么这个构造比(*buffPtr)+?有一个MISRA规则,它规定唯一允许的指针

在调试一些嵌入式代码时,我遇到了如下情况:

buffPtr = &a[5];
buffEndPtr = &a[10];

while (buffPtr != buffEndPtr) 
{ 
    *buffPtr = 0xFF; 
    buffPtr  = &buffPtr[1];         /*  MISRA improvement for: buffPtr++ */ 
}

为什么这个构造比(*buffPtr)+?

有一个MISRA规则,它规定唯一允许的指针数学是索引操作

您所展示的模式是执行得很差的变通方法。这是丑陋的/怪异的/不寻常的,并且可能是基于对该规则目的的误解。它还可能违反另一条规则

编写此代码的更好方法是:

for(i=5; i < 10; i++)
{
    a[i] = 0xff;
}
(i=5;i<10;i++)的

{
a[i]=0xff;
}
更新2015-05-20-由于这是公认的答案,这是违反的实际规则,由embedded.kyle提供:

MISRA-C:2004,规则17.4(必需)或MISRA-C:2012,规则18.4(必需) 数组索引应是指针算法的唯一允许形式

(*buffPtr)+
违反的规则是:

MISRA-C:2004,规则17.4(必需)或MISRA-C:2012,规则18.4(必需)

数组索引应是指针算法的唯一允许形式

他们在这条规则背后的理由是:

使用数组下标语法
ptr[expr]
的数组索引是 指针算术的首选形式,因为它通常更清晰和 因此,比指针操作更不容易出错。任何明确的 计算出的指针值有可能访问非预期的或 无效的内存地址。这种行为在数组中也是可能的 索引,但下标语法可以简化手动检查的任务

C语言中的指针算法可能会使初学者对表达式感到困惑
ptr+1
可能被错误地解释为将
1
添加到 存放在
ptr
中的地址。实际上,新的内存地址取决于 指针目标的大小(字节)。这种误解可能导致 如果
sizeof
应用不正确,将导致意外行为

米斯拉的许多规则都有类似的原理。基本上,他们的思维过程是,如果您尽可能简单、明确地编写代码,那么代码将更具可读性和可维护性,从而生成本质上更安全的代码。安全代码是MISRA标准背后的目的


正如Brian指出的,有一些方法可以编写符合MISRA的代码,但仍然违反了规则背后的意图。在我看来,Brian的
for
循环示例是最常见和最容易理解的构造。

在MISRA-C:2004规则17.4中,有一条禁止所有形式指针算术的建议规则。意图是好的,该规则的目的是试图禁止潜在的危险代码,例如:

stuff* p; 
p = p + 5; // 5 stuff, not 5 bytes, bug or intentional?
以及难以阅读的代码,例如

*(p + 5) = something;  // harder to read but equivalent to p[5]
一般来说,在循环指向数据时,建议使用整数迭代器而不是指针算术

但是,该规则还禁止了可能不危险的各种基本指针操作,例如
ptr++
。一般来说,这条规定太严格了

在MISRA-C:2012中,该规则(18.4)被放宽,仅禁止
+-+=-=
运算符


在您的例子中,
buffPtr=&buffPtr[1]
是一个试图规避规则17.4的误导行为,因为该规则没有多大意义。相反,程序员决定混淆他们的程序,使其可读性降低,因此安全性降低

正确的处理方法是使用++运算符并忽略规则17.4。这是一条咨询规则,因此不需要进行任何偏离(除非当地MISRA-C实施部门出于某种原因另有规定)。如果您确实需要偏离,您可以简单地说该规则对++运算符没有任何意义,然后参考MISRA-C:2012 18.4

(当然,如另一个答案所示,将整个循环重写为for循环是最好的解决方案)


不使用常识的编程总是非常危险的,因为盲目地遵循MISRA而不理解规则背后的合理原理,或者在这种情况下不理解规则背后的合理原理。

因为
(*bufftr)+
是错误的。你的意思是
*bufftr++=0xFF?@mch我想这是问题正文中的一个输入错误。查看代码中的注释。原始代码肯定是规则的“变通”,而不是因为它们而“改进”。for循环是正确的模式。是的,仔细想想,我猜
memset
本身甚至不符合MISRA。因此,即使在可行的情况下,根据MISRA,这也不是正确的方法。更正:MISRA-C:2012允许+,但不允许+。它与MISRA-C:2004中引用的规则不同,也更为宽松。我认为该规则的意图是要求所有指针对象标识分配的开始,这是其他语言(如标准Pascal)的语义限制。具有这种语义限制的C方言无法完成C中可以完成的所有工作,但这种方言的实现可以以“全功能”C中无法实现的方式支持数组边界检查。在某些需要故障安全的系统中,编译器支持的数组边界检查可能会有所帮助。