在IF语句中定义的未定义变量出错

Too*_*ote 1 c gcc gcc4.8

在尝试编译以下代码片段时:

#include <stdio.h>
#include <time.h>

void change_a(int * a) {
    *a = 1;
    return;
}

void main(void) {
    int a = 0;
    change_a(&a);
    if (a) {
        time_t start = time(NULL);
    }
/* do something that never mentions a */

    if (a) {
        time_t end = time(NULL);
       printf("Time spent = %ld\n", (int) end - start);
    }
}
Run Code Online (Sandbox Code Playgroud)

GCC声明该行中的start变量未定义printf:

$ gcc --version
gcc (Debian 4.8.2-1) 4.8.2
[SNIP]
$ gcc -o test.bin test.c 
test.c: In function ‘main’:
test.c:24:44: error: ‘start’ undeclared (first use in this function)
   printf("Time spent = %ld\n", (int) end - start);
Run Code Online (Sandbox Code Playgroud)

另一方面,当将main函数更改为:时,它可以编译并正常工作:

void main(void) {
    int a = 0;
    time_t start = 0;

    change_a(&a);
    if (a) {
        start = time(NULL);
    }
    ...
Run Code Online (Sandbox Code Playgroud)

问题1

我做错了什么,或者编译器做了一些我不知道的有趣的事情?

我认为可能是编译器过于聪明并且优化了这段代码或者在其启发式或其他方面出现故障.但每隔一段时间我"发现编译器错误"总是让我错过了一些非常明显的错误.

因此,在我指责其他聪明人不那么聪明之前,我宁愿聪明的人检查一下.特别是在没有优化的情况下也会发生问题:

$ gcc -O0 -o test.bin test.c 
test.c: In function ‘main’:
test.c:24:44: error: ‘start’ undeclared (first use in this function)
   printf("Time spent = %ld\n", (int) end - start);
                                            ^
test.c:24:44: note: each undeclared identifier is reported only once for each function it appears in
Run Code Online (Sandbox Code Playgroud)

问题2

我还想知道是否有更好的方法来避免编译器错误(如果不是最后一个代码片段中的解决方法).如果我的代码错误(因为响应将包含"正确的"代码),这很明显,但我也想知道如何在某人修复GCC中的(涉嫌)错误时避免错误.

Typ*_*eIA 6

在第一个示例中,start变量在if语句的范围内声明.因此,变量超出了代码块末尾的范围(结束大括号}).这绝对不是编译器错误.

您的"解决方法"是正确的解决方案.

有关变量作用域如何在C/C++(以及使用C样式作用域的许多其他语言)中工作的更全面描述,请参见此处.