为什么我可以从另一个文件调用函数(有警告),但不能在不声明的情况下使用另一个文件中的变量?

Tor*_*day 6 c

// a.c 
#include <stdio.h>

int main() {
    printf("%d", sum());
}
Run Code Online (Sandbox Code Playgroud)
// b.c 
int sum() {
   return 10;
}
Run Code Online (Sandbox Code Playgroud)

gcc a.c b.c正常编译这两个文件 ,它可以正常工作并发出implicit declaration警告,如果我suma.c. 我在另一篇文章中读到,如果我不声明函数并且正确调用它,那很好,但不建议这样做,我应该始终声明我在每个文件中使用的内容,这很好,并且可以理解。

我不明白的是为什么在另一个文件中定义的函数和变量之间存在区别。为什么我不能以与上述相同的方式使用另一个文件中定义的变量?不过,我也可以通过i在我使用它的文件中声明来让它运行。

// c.c 
#include <stdio.h>
int main() {
    printf("%d", i);
    return ;
}
Run Code Online (Sandbox Code Playgroud)
// d.c 
int i = 12;
Run Code Online (Sandbox Code Playgroud)

编译gcc c.c d.c,产生以下错误

c.c: In function ‘main’:
c.c:3:19: error: ‘i’ undeclared (first use in this function)
      printf("%d", i);
                   ^
c.c:3:19: note: each undeclared identifier is reported only once for each function it appears in
Run Code Online (Sandbox Code Playgroud)

P.P*_*.P. 6

首先,“隐式 int”规则早已不复存在(自 C99 起),并且没有理由在现代 C(即 C99 及更高版本)中提供声明。


但是,为什么函数可以使用隐式声明但变量不能使用,因为这就是它最初在预标准 C 中定义的方式(隐式规则在 C89 中也有效)。

来自 Dennis Ritchie 的C 参考手册

  1. 隐式声明

并不总是需要在声明中同时指定存储类和标识符类型。有时存储类由上下文提供:在外部定义中,以及在形式参数和结构成员的声明中。在函数内部的声明中,如果给出了存储类但没有给出类型,则假定标识符为 int;如果指定了类型但未指定存储类,则假定标识符为 auto。后一条规则的一个例外是函数,因为自动函数是没有意义的(C 无法将代码编译到堆栈中)。如果标识符的类型是“函数返回...”,则隐式声明为 extern。在表达式中,后跟 ( 并且当前未声明的标识符在上下文中被声明为“函数返回 int”。

未后跟 ( 的未定义标识符被假定为稍后将在函数中定义的标签。(由于标签不是左值,因此在使用未声明的标识符时有时会注意到“需要左值”错误消息。 ) 自然地,作为标签的标识符的出现表明它是这样的。

(强调我的)

这意味着以下是可以的:

// assumed to return int
func()
{
    return 0;
}


// Type of 'some_var' defaults to int
void func2(some_var)
{
}
Run Code Online (Sandbox Code Playgroud)

但这不行:

int func()
{
    // Assumed to be labels; it's undeclared variable.
    i;
}
Run Code Online (Sandbox Code Playgroud)