0

我有一个非常快速的问题。使用哪个更“标准”?转到或返回一个函数?

转到示例:

main(){
   start:
   //some code
   goto start;
}

main(){
   //some code
   return main();
}

两者都会循环脚本。但我想知道哪个更适合使用。

goto 似乎真的很好,但是使用它有什么缺点吗?(我只是想知道,因为 goto 函数 Oo 让一位同学失败了,我想知道为什么,或者他所做的事情是合理的。)

如果您问为什么要问这个,我正在尝试创建一个带有子菜单的菜单,其中子菜单包含“返回”选项(我会使用 goto 或 return)

4

5 回答 5

10

这里合理的做法是使用循环。它具有与 a 相同的效果,goto但被认为是更好的实践,因为它遵循结构化编程的规则,而不是以前常见的不可维护的面条汤编程。

int main(void) {
   while (1) {
      //some code
   }
}

如果递归具有明确定义的限制,则递归调用函数也可以被认为是好的风格。C 中的无限递归通常会导致堆栈溢出错误,因为很少有编译器实现尾调用优化。

于 2013-08-19T09:51:05.407 回答
3

goto应该避免。实际上,使用它被认为是一种不好的做法,因为它使代码更难阅读和理解。

我不确定这return main();是否正确,在我看来它非常丑陋且不安全。

执行无限循环的更好解决方案是使用while(1)or for(;;)

于 2013-08-19T09:51:36.720 回答
1

考虑到你需要这个做什么,循环和函数可以解决问题:

void submenu(void)
{
    for (;;)
    {
        printf("a: Do something else\n");
        printf("b: Leave sub menu\n");

        char choice;
        scanf(" %c", &choice);
        if (choice == 'a')
            do_something_else();
        else if (choice == 'b')
            break;  /* Break out of loop */
        else
            printf("Invalid choice.\n");
    }

    /* When this function returns, you get back to the main menu */
}

void mainmenu(void)
{
    int goon = 1;

    while (goon)
    {
        printf("1: Do something\n");
        printf("2: Enter sub-menu\n");
        printf("3: Exit\n");

        char choice;
        scanf(" %c", &choice);

        switch (choice)
        {
        case '1':
            do_something();
            break;

        case '2':
            /* Enter the sub-menu */
            submenu();
            break;

        case '3':
            goon = 0;  /* This will cause the loop to end */
            break;

        default:
            printf("Invalid choice.\n");
            break;
        }
    }
}

int main(int, char **)
{
    mainmenu();
    return 0;
}
于 2013-08-19T10:20:32.453 回答
0

goto例如,当您有难以从 using 中返回的深层嵌套循环时,您应该使用break
当您使用returnin时,main您将结束主功能并将控制权返回给操作系统。

您的goto-implementation 导致无限循环,并且远未完成与 return 相同的操作。此外,您永远不应该main()直接或间接调用。

无限循环将使用任一实现

for(;;)

或者

while(1)

这些更常见,但如果您没有明确调用break循环中的任何位置,您的程序将永远不会结束。

于 2013-08-19T09:49:42.447 回答
0

return main()可能是个坏主意,因为您不能保证编译器会优化额外的堆栈帧。如果编译器未能做到这一点,那么您的堆栈将在循环的每次迭代中继续增长。

它确实会重新初始化您的局部变量,但您可以通过将这些变量放入循环构造中来获得相同的效果。

goto可能在某些代码中占有一席之地,但事实并非如此。如果你想循环,那么有循环结构。改为使用for (;;) { /* some code */ }

于 2013-08-19T10:45:01.657 回答