计算函数返回值的最佳实践

Fed*_*ico 8 c return misra

我经常在C中构建函数来检查一些参数并返回错误代码.

当我发现错误时停止值检查的最佳方法是什么?

第一个例子:

ErrorCode_e myCheckFunction( some params )
{
  ErrorCode_e error = CHECK_FAILED;

  if( foo == bar )
  {
     if( foo_1 == bar_1 )
     {
        if( foo_2 == bar_2 )
        {
           error = CHECK_SUCCESS;
        }
     }
  }

  return error;
}
Run Code Online (Sandbox Code Playgroud)

第二个例子:

ErrorCode_e myCheckFunction( some params )
{
  if( foo != bar )
  {
     return CHECK_FAILED;
  }

  if( foo_1 != bar_1 )
  {
     return CHECK_FAILED;
  }

  if( foo_2 != bar_2 )
  {
     return CHECK_SUCCESS;
  }
}
Run Code Online (Sandbox Code Playgroud)

我更喜欢第一种方法,因为我读到MISRA规则避免多次返回语句.

哪种方法最好?

Lun*_*din 19

第二个是最好的,因为它更容易阅读,随着复杂性的增加而很好地扩展,并且在出错时立即停止执行该功能.当您在函数内部进行大量错误处理时,这是编写此类函数的唯一合理方法,例如,如果函数是解析器或协议解码器.

MISRA-C在函数中不允许多个返回语句是MISRA-C的缺陷.据说这意味着不允许从各处返回的意大利面条代码,但是教条地禁止多个返回语句实际上可以使代码的可读性大大降低,正如我们从您的示例中看到的那样.想象一下,如果你需要检查10个不同的错误.然后你会有10个复合if语句,这将是一个难以理解的混乱.

我曾多次向MISRA委员会报告此缺陷,但他们没有听过.相反,MISRA-C只是盲目引用IEC 61508作为规则的来源.这反过来只列出了这个规则的一个可疑来源(IEC 61508:7 C.2.9),它是1979年的恐龙编程书.

这不是专业的,也不是科学的 - MISRA-C和IEC 61508(和ISO 26262)都应该感到羞耻(直接或间接地)将1979年的主观无意义列为其唯一来源和理由.

只需使用第二种形式,并针对此缺陷MISRA规则提出永久性偏差.

  • 我同意你。当需要检查几个参数时,第二种方法是最好的。专门用于代码可读性。 (2认同)
  • @Andrew缺陷=可疑来源。话虽如此,对于任何C程序员来说,上面问题中的第二版都比第一版更具可读性是很清楚的。特别是随着错误检查数量的增加。实际上,这里有3种选择:1)嵌套的复合语句疯狂,2)出错时返回,或3)BASIC上的“出错时跳转”。第一个是不可读且难以维护的,第二个是可读性强的代码,第三个是可以接受的,但不如第二个可读。MISRA-C:2004仅允许1)。MISRA-C:2012仅允许1)和3)。这不是缺陷吗? (2认同)
  • 规则15.5是*咨询*-如果您可以证明该决定的合理性,请不予采用:-) (2认同)
  • 是的......它被重新分类为:2012 :-) (2认同)
  • 我认为更好的规则是说一个函数可能在第一个副作用之前有任意数量的提前退出返回,并且可能在导致副作用的最后一个语句之后有多个返回,或导致副作用本身的单一回报。我认为应该允许最合理的用例,同时禁止最不合理的用例。 (2认同)