我们的组织有一个必要的编码规则(没有任何解释):
if ... else如果构造应该用else子句终止
例1:
if ( x < 0 )
{
   x = 0;
} /* else not needed */
Run Code Online (Sandbox Code Playgroud)
例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 */
}
Run Code Online (Sandbox Code Playgroud)
这个设计要处理的边缘情况是什么?
关于其原因的另一个问题是,示例1不需要,else但示例2不需要.如果原因是可重用性和可扩展性,我认为else应该在两种情况下都使用.
Lun*_*din 146
正如另一个答案中所提到的,这是来自MISRA-C编码指南.目的是防御性编程,这是一种常用于任务关键型编程的概念.
也就是说,每个if - else if必须以一个结束else,并且每一个switch必须以一个结束default.
有两个原因:
自我记录代码.如果你写了一个else但是把它留空了就意味着:"我确实认为这个场景既不是真的if也不else if是真的".
不写else那里就意味着:"要么我考虑的情况既不是真的,if也不else if是真的,或者我完全忘记考虑它,并且我的代码中可能存在一个很大的错误".
停止失控代码.在任务关键型软件中,您需要编写可靠的程序,即使是极不可能的程序.所以你可以看到像这样的代码
if (mybool == TRUE) 
{
} 
else if (mybool == FALSE) 
{
}
else
{
  // handle error
}
Run Code Online (Sandbox Code Playgroud)
这段代码与PC程序员和计算机科学家完全不同,但它在任务关键型软件中非常有意义,因为它捕获了"mybool"因任何原因而腐败的情况.
从历史上看,由于EMI /噪声,您会担心RAM存储器的损坏.今天这不是什么大问题.更有可能的是,由于代码中其他地方的错误导致内存损坏:指向错误位置的指针,数组越界错误,堆栈溢出,失控代码等.
因此,大多数情况下,当您在实现阶段编写错误时,这样的代码会重新出现在脸上.这意味着它也可以用作调试技术:您编写的程序会在您编写错误时告诉您.
编辑
关于为什么else每一个单后都不需要if:
一个if-else或if-else if-else完全覆盖变量可以具有的所有可能值.但是,一个简单的if陈述不一定涵盖所有可能的值,它有更广泛的用法.大多数情况下,您只是希望检查某个条件,如果不满足,则不执行任何操作.那么编写防御性编程来覆盖else案例根本没有意义.
如果你else在每一个之后写一个空的话,它会完全混乱代码if.
MISRA-C:2012 15.7没有理由说明为什么else不需要,它只是声明:
注意:
else简单if语句不需要最终语句.
Emb*_*d C 61
贵公司遵循MISRA编码指南.这些指南的一些版本包含此规则,但来自MISRA-C:2004 †:
规则14.10(必填):所有if ... else如果构造应以else子句终止.
只要if语句后跟一个或多个else语句,此规则就适用; 最后的其他部分
if后面应有一份else声明.在简单if陈述的情况下,则else不需要包括该陈述.最终else声明的要求是防御性编程.该else声明应要么采取适当的行动或含有适当的评论,为什么不采取行动.这与default在switch声明中具有最终子句的要求一致.例如,此代码是一个简单的if语句:Run Code Online (Sandbox Code Playgroud)if ( x < 0 ) { log_error(3); x = 0; } /* else not needed */而下面的代码演示的
if,else if构造Run Code Online (Sandbox Code Playgroud)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
}
Run Code Online (Sandbox Code Playgroud)
在常规使用中,在使用时不需要一直执行操作if.
示例2: 
程序员在此检查n个条件并执行多个操作.在常规使用if..else if中,switch您可能需要执行默认操作.因此else根据misra标准需要使用
if(condition_1 || condition_2 || ... condition_n)
{
   //operation_1
}
else if(condition_1 || condition_2 || ... condition_n)
{
  //operation_2
}
....
else
{
   //default cause
}
Run Code Online (Sandbox Code Playgroud)
†这些出版物的当前版本和过去版本可通过MISRA网上商店(通过)购买.
Jee*_*tel 19
这相当于在每个交换机中都要求默认情况.
这个额外的其他内容将减少程序的代码覆盖率.
根据我将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.
        */
}
Run Code Online (Sandbox Code Playgroud)
        只是一个简短的解释,因为我大约在5年前做过这个.
(大多数语言)没有语法要求包含"null" else语句(和不必要的{..}),而在"简单的小程序"中则没有必要.但真正的程序员不会编写"简单的小程序",同样重要的是,他们不会编写将被使用过一次然后丢弃的程序.
当写一个if/else时:
if(something)
  doSomething;
else
  doSomethingElse;
Run Code Online (Sandbox Code Playgroud)
一切看起来都很简单,甚至连添加点都看不到{..}.
但是有一天,从现在开始的几个月,其他一些程序员(你永远不会犯这样的错误!)将需要"增强"程序并添加一个声明.
if(something)
  doSomething;
else
  doSomethingIForgot;
  doSomethingElse;
Run Code Online (Sandbox Code Playgroud)
突然doSomethingElse有点忘记它本应该在else腿上.
所以你是一个优秀的小程序员,你总是使用{..}.但你写道:
if(something) {
  if(anotherThing) {
    doSomething;
  }
}
Run Code Online (Sandbox Code Playgroud)
一切都很好,直到新的孩子进行午夜修改:
if(something) {
  if(!notMyThing) {
  if(anotherThing) {
    doSomething;
  }
  else {
    dontDoAnything;  // Because it's not my thing.
  }}
}
Run Code Online (Sandbox Code Playgroud)
是的,它的格式不正确,但是项目代码的一半,"自动格式化程序"被所有#ifdef语句搞砸了.当然,真正的代码比这个玩具示例复杂得多.
不幸的是(或者不是),我已经出现了几年这样的事情,所以我没有一个新的"真实"的例子 - 上面(显然)做作和一点点.
这样做是为了使代码更具可读性,以便以后的引用,并向后来的审阅者明确说明,最后一个处理的其余案例else都不做任何事情,这样他们一见钟情就不会被忽视.
这是一个很好的编程实践,它使代码可以重用和扩展.
我想补充 - 并且部分地反驳 - 以前的答案.虽然使用if-else肯定是常见的,如果以类似开关的方式覆盖表达式的全部可思考值,则无法保证完全覆盖任何可能的条件范围.关于switch构造本身也可以这样说,因此需要使用default子句,它捕获所有剩余的值,并且如果不是其他方面的话,可以用作断言保护.
问题本身具有一个很好的反例:第二个条件与x完全无关(这就是为什么我经常更喜欢基于开关的变体更灵活的基于if的变体).从示例中可以明显看出,如果满足条件A,则应将x设置为某个值.如果不满足A,则测试条件B. 如果满足,则x应该接收另一个值.如果既不满足A也不满足B,则x应保持不变.
在这里我们可以看到应该使用一个空的else分支来评论程序员对读者的意图.
另一方面,我不明白为什么必须有一个else子句特别是对于最新的和最里面的if语句.在C中,没有'else if'这样的东西.只有if和else.相反,根据MISRA,构造应该正式以这种方式缩进(我应该将开头的花括号放在他们自己的行上,但我不喜欢这样):
if (A) {
    // do something
}
else {
    if (B) {
        // do something else (no pun intended)
    }
    else {
        // don't do anything here
    }
}
Run Code Online (Sandbox Code Playgroud)
当MISRA要求在每个分支周围放置花括号时,它通过提及"if if else if constructs"而自相矛盾.
任何人都可以想象如果其他树木深深嵌套的丑陋,请参阅旁注.现在想象一下这个结构可以在任何地方任意扩展.然后最后要求一个else子句,而不是其他任何地方,变得荒谬.
if (A) {
    if (B) {
        // do something
    }
    // you could to something here
}
else {
    // or here
    if (B) { // or C?
        // do something else (no pun intended)
    }
    else {
        // don't do anything here, if you don't want to
    }
    // what if I wanted to do something here? I need brackets for that.
}
Run Code Online (Sandbox Code Playgroud)
因此,我确信制定MISRA指南的人员如果考虑到意图,就会有类似开关的if-else.
最后,它归结为他们准确定义"if ... else if construct"的含义
基本原因可能是代码覆盖和隐含的其他:如果条件不正确,代码将如何表现?对于真正的测试,您需要一些方法来确定您已经使用条件false进行了测试.如果您拥有的每个测试用例都经过了if子句,那么由于您没有测试的条件,您的代码可能在现实世界中出现问题.
但是,某些条件可能与示例1类似,例如在纳税申报单上:"如果结果小于0,则输入0".您仍然需要在条件为假的情况下进行测试.
|   归档时间:  |  
           
  |  
        
|   查看次数:  |  
           12195 次  |  
        
|   最近记录:  |