[英]Unpermitted operand to operator '++' [MISRA 2012 Rule 10.1, required]
I am trying to fix the Misra warning for the modules written by others. 我正在尝试为其他人编写的模块修复Misra警告。 I observed that
++
operation is being used on the enum
. 我观察到在
enum
上使用了++
操作。
I referred SE question which talks on the same topic. 我提到了关于同一主题的SE问题 。 How do I resolve this error?
如何解决此错误? Do I need to suggest the module owner, to change the implementation?
我是否需要建议模块所有者来更改实现?
#include <stdio.h>
typedef enum
{
COMPARE = 0,
INCONSISTENT = 10,
WRITE,
READ,
FINISHED
}TestsType;
static TestsType CurrentTest;
void fun1(void)
{
if(READ != CurrentTest)
{
CurrentTest++;
}
else
{
CurrentTest = FINISHED;
}
}
int main(void) {
// your code goes here
CurrentTest = COMPARE;
fun1();
printf("%d", CurrentTest);
return 0;
}
I kept the enum
like this in code purposefully to understand any impact. 我故意将这样的
enum
保留在代码中以了解任何影响。 However, in actual code, it is as below. 但是,在实际代码中,如下所示。
typedef enum
{
COMPARE,
INCONSISTENT,
WRITE,
READ,
FINISHED
}TestsType;
Incrementing an enum is just wrong! 增加一个枚举是错误的!
enums were added to the language as a better alternative to #define for a number of constants, and were considered ints in other respects (ie a const array of ints). 枚举被添加到语言中,作为对#define的更好的替代,它包含多个常量,并且在其他方面也被视为int(即,int的const数组)。 To enforce anything more would require run-time checking.
要强制执行其他任何操作,都需要运行时检查。
As enum values don't have to be contiguous, incrementing them makes no sense when they're treated as integers. 由于枚举值不必是连续的,因此当将它们视为整数时,将它们递增是没有意义的。 If a compiler does allow it, it thinks it's incrementing an int, which can mean your value doesn't correspond to any value in the enum afterwards.
如果编译器确实允许它,它会认为它正在增加一个int,这可能意味着您的值此后与枚举中的任何值都不对应。
So my advice is "don't do it" even if a particular compiler lets you. 因此,即使特定的编译器允许您这样做,我的建议还是“不要这样做”。 Rewrite it to something explicit.
将其重写为明确的内容。
If you want to cycle through a particular range of states represented by contiguous integers, you CAN use an enum but only if you make its values contiguous too. 如果要循环显示由连续整数表示的特定状态范围,则可以使用枚举,但前提是必须使其值也连续。 Put lots of warnings about the definition explaining not to tinker.
在定义上放很多警告,以解释不要修改。 Then increment an int representing the state, which can then be compared to the enum safely.
然后增加一个表示状态的int,然后可以将其安全地与枚举进行比较。
The whole point of using a standard like MISRA is to avoid risky code . 使用诸如MISRA之类的标准的全部目的是避免风险代码 。 And there's no question but that incrementing enums is risky.
毫无疑问,但是增加枚举是有风险的。
If you've got some code that increments enums, and it works well (under all conditions), it's only because of a number of interlocked assumptions and conventions which probably aren't all written down and which almost certainly won't be obvious to (and honored by) a later maintenance programmer. 如果您有一些可以递增枚举的代码,并且在所有条件下都可以正常工作,那仅仅是因为有许多相互关联的假设和惯例,这些假设和惯例可能并没有全部写下来,并且几乎可以肯定不会(并得到后来的维护程序员的尊重)。
So, indeed, there is no simple fix for this. 因此,确实,没有简单的解决方案。 Any simple fix (which might get your MISRA checker to shut up) will likely leave the inherent risks in the practice all intact -- that is, you might satisfy the letter of MISRA, but not the spirit (which is obviously backwards).
任何简单的修复(可能会使您的MISRA检查器关闭)都可以保留实践中的固有风险,也就是说,您可能会满足MISRA的要求,但不能满足要求(显然是落后的)。
So yes, you should require (not just suggest) that the module owner change the implementation. 因此,是的,您应该(不仅仅建议)要求模块所有者更改实现。
What might the revised implementation look like? 修改后的实现会是什么样子? I think it should have one or more of the following aspects:
我认为它应该具有以下一个或多个方面:
int
and some #define
d constants. int
和一些#define
d常量。 enum state {
OFF = 0,
LOW = 3,
MEDIUM,
HIGH,
EXCEPTIONAL = 10
};
/* States LOW..HIGH are assumed to be contiguous. Make sure you keep them so! */
/* If (and only if) you add or subtract states to the contiguous list, */
/* make sure to also update N_CONTIGUOUS_STATES. */
#define N_CONTIGUOUS_STATES 3
enum state nextstate(enum state oldstate)
{
/* Normally performing arithmetic on enums is wrong. */
/* We're doing so here in a careful, controlled, constrained way, */
/* limited just to the values LOW..HIGH which we're calling "contiguous". */
assert((int)LOW + N_CONTIGUOUS_STATES - 1 == (int)HIGH);
if(oldstate >= LOW && oldstate < HIGH) {
return (enum state)((int)oldstate + 1);
} else {
/* perform arbitrary mappings between other states */
}
}
The intent here is both to document what's going on, and ensure that if a later maintenance programmer changes the enum definition in any way that breaks the assumption that there are some consecutive states between which straight incrementation is allowed, the assertion will fail. 这样做的目的是记录发生的情况,并确保如果以后的维护程序员以任何方式改变枚举定义,从而破坏假定存在某些允许连续递增的连续状态的假设,则断言将失败。
...But I hasten to add that this is not a complete solution. ...但是我赶紧补充一点,这不是一个完整的解决方案。 An even more important guarantee to preserve is that every state transition is handled, and this is even easier to violate if a later maintenance programmer adds new states but forgets to update the transition mappings.
保留的一个更重要的保证是处理每个状态转换,而且如果以后的维护程序员添加新状态但忘记更新转换映射,则更容易违反。 One good way to have the compiler help you guarantee this is to use a
switch
statement, although this then just about forces you to make every transition explicit (that is, not to use the +1 shortcut): 让编译器帮助您保证这一点的一种好方法是使用
switch
语句,尽管这将迫使您明确每个转换(即,不使用+1快捷键):
enum state nextstate(enum state oldstate)
{
switch(oldstate) {
case OFF: return ... ;
case LOW: return MEDIUM;
case MEDIUM: return HIGH;
case HIGH: return ... ;
case EXCEPTIONAL: return ... ;
}
}
The advantage of using a switch
is that modern compilers will warn you if you leave an enum value out of a switch like this. 使用
switch
的好处是,如果您在这样的开关中遗漏枚举值,现代编译器会警告您。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.