在使用之前是否需要声明功能?如果我们不使用函数声明并直接调用它,编译器是否会出错。请按照标准C回答。
如果是,那么如果没有定义函数的参数,那么type的参数转换为int并且float为double会是什么意思?
答案 0 :(得分:4)
在ANSI C中,您不必声明函数原型;但是,使用它们是最佳实践。标准允许您不使用它们的唯一原因是为了与非常旧的代码向后兼容。
如果您没有原型,并且调用了函数,编译器将根据您传递给函数的参数推断出原型。如果稍后在同一个编译单元中声明该函数,如果函数的签名与编译器猜测的不同,则会出现编译错误。
更糟糕的是,如果函数在另一个编译单元中,则无法获得编译错误,因为没有原型就无法检查。在这种情况下,如果编译器出错,如果函数调用在堆栈上推送的函数不同于函数所期望的那样,则可能会得到未定义的行为。
约定总是在头文件中声明一个原型,该头文件与包含该函数的源文件同名。
使用原型,编译器可以验证您是否正确调用了函数(使用正确的数字和参数类型)。
没有原型,就可以拥有这个:
// file1.c
void doit(double d)
{
....
}
int sum(int a, int b, int c)
{
return a + b + c;
}
和此:
// file2.c
// In C, this is just a declaration and not a prototype
void doit();
int sum();
int main(int argc, char *argv[])
{
char idea[] = "use prototypes!";
// without the prototype, the compiler will pass a char *
// to a function that expects a double
doit(idea);
// and here without a prototype the compiler allows you to
// call a function that is expecting three argument with just
// one argument (in the calling function, args b and c will be
// random junk)
return sum(argc);
}
答案 1 :(得分:1)
在C中,您需要在使用之前定义所有内容。我认为这个想法是它可以一次性编译所有内容,因为它始终具有所需的所有信息。
我不确定你对第二部分的要求是什么。如果未定义该功能,则它将无效。
答案 2 :(得分:1)
答案简短:在C89 / 90中没有必要,在C99中是必要的。
在C89 / 90中,不必声明函数以便调用。对于未声明的函数,编译器将对函数返回类型(假定int
)和函数参数类型(将在调用点的参数类型中派生它们)做出假设。
在C99中,必须事先声明函数才能被调用。注意,即使在C99中也没有要求为函数提供原型,只需要声明,即非原型声明即可。这意味着编译器不再需要对函数返回类型做任何假设(因为声明总是明确指定它),但它仍然可能必须对函数参数做出假设(如果声明不是原型)。 / p>
答案 3 :(得分:0)
6.5.2.2“函数调用”中的C99标准描述了函数调用表达式中发生的事情,包括编译器是否没有看到该函数的原型:
如果表示被调用函数的表达式具有不包含原型的类型,则对每个参数执行整数提升,并将类型为float的参数提升为double。这些被称为默认参数
稍后,它描述了如果函数调用表达式与函数实际定义的方式不匹配会发生什么:
如果使用与表示被调用函数的表达式指向的类型(表达式)类型不兼容的类型定义函数,则行为未定义。
显然,为了帮助确保正确性,使用函数原型是正确的做法。已经足够C ++使得函数原型成为c。
的“破坏”变化之一