如果... else如果使用else子句构造,终止的好处是什么?

我们的组织有一个必要的编码规则(没有任何解释):

if ... else如果构造应该用else子句终止

例1:

if ( x < 0 )
{
   x = 0;
} /* else not needed */

例2:

if ( x < 0 )
{
    x = 0;
}
else if ( y < 0 )
{
    x = 3;
}
else    /* this else clause is required, even if the */
{       /* programmer expects this will never be reached */
        /* no change in value of x */
}

这个设计要处理什么边缘情况?

关于这个原因我还担心的是, 例1不需要else例2就是这样。 如果原因是可重用性和可扩展性,我想else应该在这两种情况下使用。


正如另一个答案中提到的,这是来自MISRA-C编码准则。 其目的是防御性编程,这是一个常用于任务关键型编程的概念。

也就是说,每个if - else if必须以else结束,并且每个switch必须以default结束。

有两个原因:

  • 自我记录代码。 如果你写了一个else但将它留空,这意味着:“我已经明确地考虑过这种情况,既不if也不else if是真的”。

    这里没有写一个else意味着:“或者我认为这种情况既不if也不else if是真的,或者我完全忘记考虑它,并且在我的代码中可能存在一个胖胖的bug。

  • 停止失控的代码。 在关键任务软件中,您需要编写强大的程序,即使对于极不可能的程序也是如此。 所以你可以看到类似的代码

    if (mybool == TRUE) 
    {
    } 
    else if (mybool == FALSE) 
    {
    }
    else
    {
      // handle error
    }
    

    此代码与PC程序员和计算机科学家完全不同,但它在任务关键型软件中非常合理,因为它捕捉到“mybool”因任何原因已经腐败的情况。

    从历史上看,由于EMI /噪声,您会担心RAM存储器的损坏。 今天这不是什么大问题。 更有可能的是,由于代码中其他地方的错误而导致内存损坏:指向错误位置的指针,数组越界错误,堆栈溢出,失控代码等。

    所以大多数情况下,当你在实现阶段编写错误时,这样的代码会回到自己的脸上。 这意味着它也可以用作调试技术:您正在编写的程序会告诉您何时编写了错误。


  • 编辑

    至于为什么else之后的每一个不需要if

    if-elseif-else if-else完全覆盖变量可能具有的所有可能值。 但是,一个普通的if语句不一定有涵盖所有可能的值,它具有更广泛的使用。 大多数情况下,你只是想检查一定的条件,如果不符合,则什么也不做。 那么编写防御性编程来覆盖else情况根本没有意义。

    加上它会如果你写一个空完全弄乱代码else每个后if

    MISRA-C:2012 15.7没有说明为什么不需要else理由,它只是指出:

    注意:简单的if语句不需要final else语句。


    您的公司遵循MISRA编码指南。 这些准则的几个版本包含此规则,但来自MISRA-C:2004†:

    规则14.10(必需):所有if ... else如果构造应以else子句终止。

    只要if语句后跟一个或多个if语句,此规则就适用; 最后if其他的if应该跟着一个else语句。 在简单的if语句的情况下, else语句不需要包含。 最后的else声明的要求是防御性编程。 else语句要么采取适当的行动,要么包含一个合适的评论,说明为什么不采取行动。 这与在switch语句中具有最终default子句的要求是一致的。 例如,这段代码是一个简单的if语句:

    if ( x < 0 )
    {
     log_error(3);
     x = 0;
    } /* else not needed */
    

    而下面的代码演示了ifelse if结构

    if ( x < 0 )
    {
     log_error(3);
     x = 0;
    }
    else if ( y < 0 )
    {
     x = 3;
    }
    else /* this else clause is required, even if the */
    { /* programmer expects this will never be reached */
     /* no change in value of x */
    }
    

    在MISRA-C:2012取代2004版本,是目前对新项目的建议,存在相同的规则,但编号为15.7。

    示例1:在单个if语句中,程序员可能需要检查n个条件并执行单个操作。

    if(condition_1 || condition_2 || ... condition_n)
    {
       //operation_1
    }
    

    在常规使用情况下, if使用的话,执行操作并不需要所有的时间。

    示例2:这里程序员检查n个条件并执行多个操作。 在常规使用if..else ifswitch一样,你可能需要执行一个像默认的操作。 所以按照misra标准, else用法是需要的

    if(condition_1 || condition_2 || ... condition_n)
    {
       //operation_1
    }
    else if(condition_1 || condition_2 || ... condition_n)
    {
      //operation_2
    }
    ....
    else
    {
       //default cause
    }
    

    †这些出版物的当前版本和过去版本可通过MISRA网上商店(通过)购买。


    这相当于在每个交换机中都需要默认情况。

    这额外的将会减少程序的代码覆盖率。


    在我将linux内核或android代码移植到不同平台的经验中,很多时候我们做了一些错误的事情,并且在logcat中我们看到一些错误,如

    if ( x < 0 )
    {
        x = 0;
    }
    else if ( y < 0 )
    {
        x = 3;
    }
    else    /* this else clause is required, even if the */
    {       /* programmer expects this will never be reached */
            /* no change in value of x */
            printk(" n [function or module name]: this should never happen n");
    
            /* It is always good to mention function/module name with the 
               logs. If you end up with "this should never happen" message
               and the same message is used in many places in the software
               it will be hard to track/debug.
            */
    }
    
    链接地址: http://www.djcxy.com/p/15237.html

    上一篇: What is the benefit of terminating if … else if constructs with an else clause?

    下一篇: Avoiding the JMP in the JMP CALL POP technique for shellcode NASM?