goto语句的行为

时间:2015-01-08 14:52:53

标签: c goto

#include<stdio.h>

int main()  {

    int i;
    goto l;

    for(i = 0; i < 5; i++) {
        l:printf("Hi\n");
    }

    return 0;

}

上面的代码给出了三次输出Hi。我不知道它是怎么发生的,请你说出来。如果我减少5到3的值,那么只有Hi打印一次。

2 个答案:

答案 0 :(得分:2)

您正在进行比较i < 5并在i循环中递增for而不首先初始化导致未定义的行为(此时 i的值是一个随机的垃圾

如果你试试这个

#include<stdio.h>

int main()
{
    int i = 0;

    goto l;
    for(i = 0 ; i < 5 ; i++)
        l: printf("Hi\n");

    return 0;
}

它将定义行为,此程序将打印Hi 5次。

要看看发生了什么,请尝试

#include<stdio.h>

int main()
{
    int i = 4;

    goto l;
    for(i = 0 ; i < 5 ; i++)
        l: printf("Hi\n");

    return 0;
}

Hi只会打印一次,因为一旦您输入for循环,i == 4

所以基本上你正在跳这一行

for(i = 0 ; i < 5 ; i++)

由于上述原因,未能初始化i并因此导致未定义的行为。

使用goto并不总是坏事,但是当它用于控制程序流程时,很难遵循代码并理解它的作用,而且通常不需要那,但它在某些情况下确实有用,例如考虑这种情况

FILE *file;
int  *x;
int  *y;

file = fopen("/path/to/some/file", "r");
if (file == NULL)
    return IO_ERROR_CODE;

x = malloc(SomeSize * sizeof(int));
if (x == NULL)
{
    fclose(file);
    return MEMORY_EXHAUST_ERROR_CODE;
}

y = malloc(SomeSize * sizeof(int));
if (y == NULL)
{
    free(x);
    fclose(file);
    return MEMORY_EXHAUST_ERROR_CODE;
}

return SUCESS_CODE;

所以你必须在每个函数出口点添加越来越多的代码,但你可以这样做

    FILE *file = NULL;
    int  *x    = NULL;
    int  *y    = NULL;

    file = fopen("/path/to/some/file", "r");
    if (file == NULL)
        return SOME_ERROR_CODE;
    x = malloc(SomeSize * sizeof(int));
    if (x == NULL)
        goto abort;
    y = malloc(SomeSize * sizeof(int));
    if (y == NULL)
        goto abort;

    return SUCCESS_CODE;

abort:
    if (x != NULL)
        free(x);
    if (y != NULL)
        free(y);
    if (file != NULL)
        fclose(file);
    return MEMORY_EXHAUST_ERROR_CODE;

当然,在您的示例中,绝对没有理由使用goto

答案 1 :(得分:2)

您的代码展示Undefined Behavior。这是因为当程序的执行到达goto语句时,程序的执行会跳转到for循环的主体内部,从而跳过for循环的初始化部分。因此,i未初始化,并且包含&#34;垃圾值&#34;。

作为旁注:Using gotos are considered to be bad practice因为它使您的代码更难以阅读/维护。