Adr*_*ciu 13 c embedded pointers misra
在调试一些嵌入式代码时,我遇到了类似这样的事情:
buffPtr = &a[5];
buffEndPtr = &a[10];
while (buffPtr != buffEndPtr)
{
*buffPtr = 0xFF;
buffPtr = &buffPtr[1]; /* MISRA improvement for: buffPtr++ */
}
Run Code Online (Sandbox Code Playgroud)
为什么这个结构会改进(*buffPtr)++?
Bri*_*and 12
有一个MISRA规则,规定允许的唯一指针是索引操作.
您展示的模式是执行不良的解决方案.这是丑陋/怪异/不常见,可能是基于对该规则的目的的误解.它也可能违反另一条规则.
编写此代码的更好方法是:
for(i=5; i < 10; i++)
{
a[i] = 0xff;
}
Run Code Online (Sandbox Code Playgroud)
更新2015-05-20 - 由于这是接受的答案,这里违反了实际规则,由embedded.kyle提供:
MISRA-C:2004,规则17.4(必需)或MISRA-C:2012,规则18.4(必需)数组索引应是唯一允许的指针算术形式.
emb*_*yle 10
(*buffPtr)++违反的规则是:
MISRA-C:2004,规则17.4(必填)或MISRA-C:2012,规则18.4(必填)
数组索引应该是唯一允许的指针算术形式.
他们在这条规则背后的推理:
使用数组下标语法的数组索引
ptr[expr]是指针算法的首选形式,因为它通常比指针操作更清晰,因此更不容易出错.任何显式计算的指针值都有可能访问非预期或无效的内存地址.使用数组索引也可以实现这种行为,但下标语法可以简化手动审查的任务.C中的指针算法可能会让新手感到困惑.表达式
ptr+1可能被错误地解释为对1保存的地址的添加ptr.实际上,新的内存地址取决于指针目标的字节大小.如果sizeof应用不正确,这种误解可能会导致意外行为.
MISRA的许多规则都有类似的理由.基本上他们的思维过程是,如果你尽可能简单明了地编写代码,代码将更易读和可维护,从而导致本身更安全的代码.更安全的代码是MISRA标准背后的目的.
正如Brian指出的那样,有一些方法可以编写符合MISRA标准的代码,但仍然违反了规则背后的意图.for在我看来,Brian的循环示例将是最常见且易于理解的构造.
在MISRA-C:2004规则17.4中,有一条禁止所有形式的指针算法的咨询规则.意图是好的,规则的目的是试图禁止潜在的危险代码,例如:
stuff* p;
p = p + 5; // 5 stuff, not 5 bytes, bug or intentional?
Run Code Online (Sandbox Code Playgroud)
和难以阅读的代码,如
*(p + 5) = something; // harder to read but equivalent to p[5]
Run Code Online (Sandbox Code Playgroud)
通常,当循环遍历指向数据时,目的是建议使用整数迭代器而不是指针算法.
但是,该规则还禁止了各种可能不危险的基本指针操作ptr++.一般来说,规则太严格了.
在MISRA-C:2012中,这条规则(18.4)被放宽,只禁止+ - += -=运营商.
在你的情况下,这buffPtr = &buffPtr[1];是一个被误导的躲避规则17.4的企图,因为规则没有多大意义.相反,程序员决定混淆他们的程序,使其可读性降低,因此安全性降低.
处理这个问题的正确方法是使用++运算符并忽略规则17.4.这是一个咨询规则,因此不需要做任何偏差(除非出于某种原因本地MISRA-C实施另有说明).如果你确实需要偏离,你可以简单地说该规则对++运算符没有任何意义,然后参考MISRA-C:2012 18.4.
(当然,将整个循环重写为for循环,如另一个答案中所示,是最佳解决方案)
不使用常识进行编程总是非常危险,因为盲目地遵循MISRA而不理解规则背后的合理理由,或者在这种情况下缺乏这样的规则.
| 归档时间: |
|
| 查看次数: |
5438 次 |
| 最近记录: |