这个问题实际上是不久前在programming.reddit.com 上进行有趣讨论的结果.它基本归结为以下代码:
int foo(int bar)
{
int return_value = 0;
if (!do_something( bar )) {
goto error_1;
}
if (!init_stuff( bar )) {
goto error_2;
}
if (!prepare_stuff( bar )) {
goto error_3;
}
return_value = do_the_thing( bar );
error_3:
cleanup_3();
error_2:
cleanup_2();
error_1:
cleanup_1();
return return_value;
}
Run Code Online (Sandbox Code Playgroud)
goto这里的使用似乎是最好的方法,导致所有可能性中最干净,最有效的代码,或者至少在我看来.在Code Complete中引用Steve McConnell :
goto在分配资源,对这些资源执行操作,然后释放资源的例程中很有用.使用goto,您可以清理代码的一部分.goto可以降低忘记在检测到错误的每个位置释放资源的可能性.
此方法的另一个支持来自本节中的" Linux设备驱动程序"一书.
你怎么看?这种情况goto在C中是否有效?您是否更喜欢其他方法,这些方法会产生更复杂和/或效率更低的代码,但是要避免goto?
我有点不寻常的情况 - 我想使用goto语句跳转到循环中,而不是跳出它.
有充分理由这样做 - 这段代码必须是某个函数的一部分,它在第一次调用后进行一些计算,返回请求新数据并需要再继续调用一次.函数指针(明显的解决方案)无法使用,因为我们需要与不支持函数指针的代码进行互操作.
我想知道下面的代码是否安全,即它将由所有符合标准的C/C++编译器正确编译(我们需要C和C++).
function foo(int not_a_first_call, int *data_to_request, ...other parameters... )
{
if( not_a_first_call )
goto request_handler;
for(i=0; i<n; i++)
{
*data_to_request = i;
return;
request_handler:
...process data...
}
}
Run Code Online (Sandbox Code Playgroud)
我已经研究过标准,但是关于这种用例的信息并不多.我也想知道是否更换为等效,同时将但从便携性点有益的.
提前致谢.
UPD:感谢所有评论过的人!
对所有评论者:)是的,我明白我不能跳过局部变量的初始化器,我必须i在每次调用时保存/恢复.
关于强大的原因:)这段代码必须实现反向通信接口.反向通信是一种试图避免使用函数指针的编码模式.有时,它有它,因为预计你遗留代码中使用会使用它.
不幸的是,r-comm-interface无法以很好的方式实现.您不能使用函数指针,也无法轻松地将工作拆分为多个函数.
我正在编写一个需要良好错误处理的C程序.代码喜欢这样:
If(doWork("A")<0){
return -1;
}
If(doWork("B")<0){
undoWork("A");
return -1;
}
If(doWork("C")<0){
undoWork("A");
undoWork("B");
return -1;
}
return 0;
Run Code Online (Sandbox Code Playgroud)
这段代码有效,但看起来非常混乱,特别是我有一长串doWork(X)要打电话.在这种情况下,是否有更好更清洁的方法来处理错误?
我想学习一种适用于以下场景的通用清理方法.请记住,这只是 - = SAMPLE = - .
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
unsigned char *uchar1, *uchar2, *uchar3;
if ((uchar1 = malloc(sizeof(*uchar1) * 10)) == NULL) {
fprintf(stderr, "Error: malloc(uchar1);\n");
return 1;
}
if ((uchar2 = malloc(sizeof(*uchar2) * 10)) == NULL) {
fprintf(stderr, "Error: malloc(uchar2);\n");
free(uchar1);
return 1;
}
if ((uchar3 = malloc(sizeof(*uchar3) * 10)) == NULL) {
fprintf(stderr, "Error: malloc(uchar3);\n");
free(uchar1);
free(uchar2);
return 1;
}
/* do something */
free(uchar1);
free(uchar2);
free(uchar3);
return 0;
}
Run Code Online (Sandbox Code Playgroud)