main函数可以访问它下面的函数但不可变吗?

时间:2015-07-30 15:21:39

标签: c

考虑以下代码:

20420450901590

我的主函数如何看到并调用func()但不能使用i,这也是在main下面定义的。

4 个答案:

答案 0 :(得分:5)

快速回答:不要这样做。应在使用前显式声明所有函数和变量。早期版本的C允许您使用隐式声明,但您不应该利用它。

在C89 / C90中(有时称为" ANSI C",但这并不严格准确),如果调用没有可见声明的函数,则会创建隐式声明,假设函数返回int并获取您在调用中传递的(提升的)类型的参数。对象没有这样的隐式声明。

根据这条规则是一个坏主意。如果函数实际返回的类型不是int,或者它的参数与调用中传递的参数不匹配,则行为是未定义的,并且编译器没有义务告诉您&#39我犯了一个错误。

所有被调用的函数在被调用之前应该有一个显式声明,并且该声明应该是 prototype ,指定参数的类型。

1999年的ISO C标准放弃了隐含的int"规则,使非活动(违反约束)调用没有可见声明的函数。 (不幸的是,声明并不是原型,但你总是应该使用原型。)许多编译器仍允许使用旧规则进行调用。您应该了解如何使您的编译器至少警告此类调用。

这是您的程序的更正版本,在C89 / C90,C99和C11中有效:

void func(void);

int i;

int main(void)
{
    func();
    i = 8;
}

void func(void)
{

}

或者您可以简单地将func的定义移到main的定义之上(&#34;转发声明&#34;除非您有递归调用,否则通常不需要):< / p>

void func(void);

int i;

int main(void)
{
    func();
    i = 8;
}

void func(void)
{

}

答案 1 :(得分:4)

在C中,调用未声明的函数会触发一些规则来组成返回值和参数的类型。这是一个糟糕的想法,你应该始终启用捕获这个错误的编译器警告。传递或返回浮点值而不是int时,或者传递比int更宽的指针时,您将获得破坏。

更好的是,让您的编译器处于C99或更高版本模式,而不是C89。在C99中删除了隐式声明,因此您至少需要一个原型。

没有前向声明,没有使用全局变量的规则。

答案 2 :(得分:3)

在K&amp; R C中,函数被隐式声明返回int并在没有被声明的情况下使用它们时接受任何参数。

省略返回类型也默认为int作为返回类型,因此定义不会与隐式声明冲突。

答案 3 :(得分:2)

当自上而下解析源文件时,编译器需要在使用之前查看所有标识符的声明。 &#34;隐含的int&#34;没有显式返回类型的函数规则仅在C89 / 90中有效。它已从C99中的标准中删除。因此func()需要在C99及更高版本中使用原型。 如果您在C89 / 90模式下进行编译,那么函数func()没有错误。 GCC在C99模式下为您的代码生成以下警告(没有语句i=8):

$gcc -Wall -Wextra -std=c99 file.c

warning: implicit declaration of function func
warning: return type defaults to int

即使在C89 / 90中,也不会对变量i执行此类隐式隐式声明。一个例外是函数参数。

例如,

int main(i)
{
    func();
    i = 8;
}

没问题,因为i默认在C89 / 90中输入int。但它在C99及更高版本中无效。

为了使您的程序在现代C中有效,它应该是:

void func(); // (1) Prototype for func() 

int main(void)  // (2) return type of main() should be int
{
    func();
    extern int i; // (3) refers to the `i` tentatively defined after main()
    i = 8;
}
int i;
void func()
{

}