goto的C用法
C usage of goto
我有一个带有某种回调机制的状态机,函数由任务运行器调用。所有这一切的背后是一个状态机,它有 4 种状态,一些状态相互排斥,另一些状态可以组合,这构成了一个相当复杂的规则集。如果尝试进行任何非法操作,其中一个函数应向用户显示错误消息(为简单起见,此处 printf
):
static int state1 = 0;
static bool switch2 = 1;
void do_stuff(int value){
int errorCode = 0;
if(state1 == 1){
errorCode = -1;
goto ERROR;
}
if(state1 == 2 && switch2)
{
errorCode = 2;
goto ERROR;
}
printf("No error!");
return;
ERROR:
printf("%d", errorCode);
}
这是我能想到的最短、最简洁的方法,但人们一直认为使用 goto
是一件坏事。有没有更好的方法来解决这个问题,或者这是稳定性和维护方面的最佳方法?
goto
很少 是控制流的正确解决方案。虽然 goto
有有效的用例,但在这个特定函数中,您可以简单地将控制流重组为 if-else
分支,如下所示:
void do_stuff(int value)
{
int errorCode = 0;
if (state1 == 1)
{
errorCode = -1;
}
else if (state1 == 2 && switch2)
{
errorCode = 2;
}
else // unconditional case for no errors
{
printf("No error!");
return;
}
printf("%s", errorCode); // if control reaches here, print the error
}
据我所知,您正在使用 goto
进行错误处理,而不是状态机。
使用 goto
进行错误处理实际上是其中一种非常有用和首选的情况,而不是复杂的条件链。它允许您执行手动 RAII 而无需重复代码:
int do_stuff(...)
{
... = f1(...);
if (...)
goto ERROR_f1;
... = f2(...);
if (...)
goto ERROR_f2;
... = f3(...);
if (...)
goto ERROR_f3;
// Success
return ...;
ERROR_f3:
undo_f2(...);
ERROR_f2:
undo_f1(...);
ERROR_f1:
return ...;
}
我有一个带有某种回调机制的状态机,函数由任务运行器调用。所有这一切的背后是一个状态机,它有 4 种状态,一些状态相互排斥,另一些状态可以组合,这构成了一个相当复杂的规则集。如果尝试进行任何非法操作,其中一个函数应向用户显示错误消息(为简单起见,此处 printf
):
static int state1 = 0;
static bool switch2 = 1;
void do_stuff(int value){
int errorCode = 0;
if(state1 == 1){
errorCode = -1;
goto ERROR;
}
if(state1 == 2 && switch2)
{
errorCode = 2;
goto ERROR;
}
printf("No error!");
return;
ERROR:
printf("%d", errorCode);
}
这是我能想到的最短、最简洁的方法,但人们一直认为使用 goto
是一件坏事。有没有更好的方法来解决这个问题,或者这是稳定性和维护方面的最佳方法?
goto
很少 是控制流的正确解决方案。虽然 goto
有有效的用例,但在这个特定函数中,您可以简单地将控制流重组为 if-else
分支,如下所示:
void do_stuff(int value)
{
int errorCode = 0;
if (state1 == 1)
{
errorCode = -1;
}
else if (state1 == 2 && switch2)
{
errorCode = 2;
}
else // unconditional case for no errors
{
printf("No error!");
return;
}
printf("%s", errorCode); // if control reaches here, print the error
}
据我所知,您正在使用 goto
进行错误处理,而不是状态机。
使用 goto
进行错误处理实际上是其中一种非常有用和首选的情况,而不是复杂的条件链。它允许您执行手动 RAII 而无需重复代码:
int do_stuff(...)
{
... = f1(...);
if (...)
goto ERROR_f1;
... = f2(...);
if (...)
goto ERROR_f2;
... = f3(...);
if (...)
goto ERROR_f3;
// Success
return ...;
ERROR_f3:
undo_f2(...);
ERROR_f2:
undo_f1(...);
ERROR_f1:
return ...;
}