检查大量返回值时,c风格良好

检查大量返回值时,c风格良好,c,coding-style,C,Coding Style,有时我必须编写代码,在执行操作和检查错误条件之间交替进行(例如,调用库函数,检查其返回值,继续)。这通常会导致长时间运行,实际工作是在if语句的条件下进行的,如 if(! (data = (big_struct *) malloc(sizeof(*data)))){ //report allocation error } else if(init_big_struct(data)){ //handle initialization error } else ... 你们是怎么写

有时我必须编写代码,在执行操作和检查错误条件之间交替进行(例如,调用库函数,检查其返回值,继续)。这通常会导致长时间运行,实际工作是在if语句的条件下进行的,如

if(! (data = (big_struct *) malloc(sizeof(*data)))){
    //report allocation error
} else if(init_big_struct(data)){
    //handle initialization error
} else ...
你们是怎么写这种代码的?我查看了一些样式指南,但它们似乎更关注变量命名和空格

欢迎链接到样式指南


编辑:如果不清楚,我对这种风格的易读性不满意,我想找一些更好的。我通常这样写代码:

data = (big_struct *) malloc(sizeof(*data));
if(!data){
    //report allocation error
    return ...;
}

err = init_big_struct(data);
if(err){
    //handle initialization error
    return ...;
}

...

通过这种方式,我避免了调用if内部的函数,因为调试更容易,因为您可以检查返回值。

尽管我很难说,但这可能是从未流行过的
goto
的一种情况。我在这个主题上找到了一个链接:

不要在生产代码中使用
assert

在调试模式下,
assert
不应用于实际可能发生的事情(如
malloc
返回
NULL
),而应在不可能的情况下使用(如
C
中数组索引超出范围)


我使用的一种非常有效的方法是W.Richard Stevens在中使用的方法(代码可下载。对于他希望始终成功且对失败没有追索权的常见功能,他使用大写字母(代码垂直压缩):

err\u sys
此处显示错误,然后执行
退出(1)
。这样,您可以调用Malloc,知道如果出现问题,它将出错

UNP仍然是我读过的唯一一本书,我认为作者有代码检查所有可能失败的函数的返回值。其他每本书都说“你应该检查返回值,但我们会让你以后做”。

我倾向于

  • 将错误检查委托给包装函数(如Stevens)
  • 在出现错误时,使用
    longjmp
    模拟异常(我实际上使用Dave Hanson模拟异常)

另一个选项是使用Don Knuth来管理错误处理代码或其他类型的预处理器。只有在您为您的店铺设置规则时,此选项才可用:-)

这样的代码的唯一分组属性是它必须遵循外部强加的序列。这就是为什么将这些分配放在一个函数中,但这是一个非常弱的通用性。我无法理解为什么有些人建议放弃嵌套if的范围优势。你真的想把口红贴在猪身上(没有侮辱的意思)-代码的性质永远不会产生任何干净的东西,你最好做的是使用编译器帮助捕捉(维护)错误。坚持用if's IMHO


PS:如果我还没有说服你:如果你必须做出决定,goto解决方案会是什么样子?“如果”肯定会变得更难看,但“后进”呢?

如果你不想在你的代码中看到“后进”,你可以随时伪装它+1使用GOTO仍然是这种可怕语言的最好方法。是的,这是C代码的好实践(在C++代码中使用异常和RAII)。将资源PTR设置为空;设置then when get,并有一个公共的退出点,如果!无效的唯一的缺点是它确实会让您将所有资源变量放在函数的顶部范围(我更喜欢尽可能在本地声明)。应该注意的是,尽管这种解决方案通常适用于独立程序,但在库中以这种方式处理错误是非常糟糕的,它们永远不会意外中止。当您这样做时,除非您需要使用C++编译器编译此代码,否则我个人会放弃<代码>(BiguStult*)< /Case>强制转换。这是一个有争议的问题,但是如果你没有任何C++的要求,我认为最好别再提了。
void * Malloc(size_t size) {
    void    *ptr;
    if ( (ptr = malloc(size)) == NULL)
        err_sys("malloc error");
    return(ptr);
}