C 语言如何不用 goto、多处 return 进行错误处理?
我大概知道为什么会有这种规定了,单处 return 加禁止 goto,等于要求写这样的代码:
void foobar() {
void* a = 0, b = 0, c = 0;
do {
a = createA();
if (!a) break;
b = createB();
if (!b) break;
c = createC();
if (!c) break;
//...
} while (0);
if (c) freeC(c);
if (b) freeB(b);
if (a) freeA(a);
}
这样写倒也不是不行,就是凭空多了一个缩进,怪别扭的。
---- 分割线 ----
我至今不知道谁先发明了不允许多处 return 这种规定的,动机是什么。
是为了利于调试?增加可读性?这很有效吗?除非你在没有单步调试器的环境下,纯靠加代码打 log,单进单出可能有点意义。是为了释放资源吗?那么请看最后一段。
不允许多处 return 有一个显而易见的坏处,它会明显增加代码的缩进层次,我相信写过 c/c++ 或者 php、js 这类类 c 语言的同学都会有感觉。手机码字不方便,明天我会给出一个简单的例子。
另外在很多情况下,你必须使用很奇怪的流程才能实现单处 return,这样增加了思考成本不说,反而降低了代码的可读性。
所以我的建议是,能 return 就 return,能早 return 绝不晚 return,能用 return 减少大括号层次,坚决用。这不仅是代码格式上的考虑,深层次的动机是,早 return 的写法让代码“逻辑块”变得更小(逻辑块位于 return 和 return 之间),逻辑更单纯,一段尽早 return 的代码,一定比最后 return 的代码更好懂,也更符合直觉。
每次看到有人为了最后一行 return,在循环中记录返回值,break,然后在循环体外 return,我都觉得纯属有病。
至于 goto,平时自然是不用为好,太难把控。但是在那种依次申请资源,其中一个失败后倒序释放资源的情况中,不用 goto 纯属给自己找麻烦。刚才有朋友在评论中说 c 语言单处 return 是为了资源释放,其实当你多次 return 发现 hold 不住的时候,就应该果断上 goto。如果规范实在不让用 goto,那就只能在 while 中用 break 跳出,在结尾处用挨个释放资源。只不过这样代码不好看。