在使用函数之前先声明一个函数,它会有所不同吗?

问题描述 投票:1回答:1

这两个代码有什么区别? (《 The C Programming Language》一书的第一篇代码)声明函数并直接使用它有什么不同?

int atoi(char s[]) {
    double atof(char s[]);
    return (int) atof(s);
}

int atoi(char s[]) {
    return (int) atof(s);
}
c
1个回答
1
投票

第一个源代码示例明确告诉编译器信息,编译器必须在第二个源代码示例中进行推断。

以下讨论假设在示例中使用函数atof()之前,未以任何方式(包括文件等)声明或定义该函数。

在第一个示例中,您具有函数atof()的显式声明,该声明使编译器可以执行一些检查以确保其正确使用。

int atoi(char s[]) {
    double atof(char s[]);   // atof is a function that takes a character array and returns a double value
    return (int) atof(s);
}

通过我将其声明为extern double atof(char s[]);的方式只是为了让人类读者清楚这是一个外部函数。

在第二个示例中,编译器必须推断atof()是一个函数,并且它采用char数组。但是,编译器不知道函数的返回值类型,默认值为int

int atoi(char s[]) {
    return (int) atof(s);
}

第一个示例为编译器提供了其他明确的信息,使编译器可以检查函数的使用。第二个示例,编译器必须进行假设。

在其他源文件中使用的功能的首选过程是提供与包含正在使用的功能的源代码文件一起提供的标头或包含文件。在此头文件中将是具有外部可见性的所有函数的声明(换句话说,未在源文件中声明为static),并且该头文件将与包含已编译内容的目标代码或库文件一起提供函数定义。

随后使用该函数的任何人都将包括头文件,以便允许编译器检查他们是否正确使用了该函数。有一些检查是编译器无法提供的,或者程序员可以解决的,但是可以使用函数声明通过编译器的静态语法检查提供了基本级别的有效性检查。]

实验

使用Visual Studio 2015进行实验,即使在函数作用域内声明了函数,编译器也会记住该声明,并将该声明用作对源文件中其他任何用途的检查。同样,如果在不声明的情况下使用该函数,则编译器会生成一个声明,然后针对该声明使用该函数的其他任何地方进行检查。

记住函数声明的行为与在函数范围内声明外部变量的行为有些不同。外部变量声明仅在其声明的范围内可见。同样,如果在封装此新作用域的较高范围作用域中存在相同的变量名(使用左括号或开放括号创建),则新声明将覆盖新作用域中的先前声明。一旦新作用域终止(使用右括号或右括号),原始声明将再次可见。

例如,在下面的源代码中,第一个函数中声明的函数atof1()的声明用于验证第二个函数中函数atof1()的使用。另外,当编译器遇到正在使用的函数且未声明时,它会为函数atof2()创建一个声明,并且此创建的声明用于对使用函数atof2()的任何其他实例执行有效性检查。

int xatoi(char s[]) {
    extern double atof1(char s[]);   // atof is a function that takes a character array and returns a double value
    extern double jj;

    jj = atof1(s);      // line 106
    jj = atof2(s);      // line 107, undeclared undefined function, compiler creates declaration, assumes function returns int
    return (int)jj;     // line 108
}

int xato2(char s[])
{
    int kk;             // line 113
    jj = atof1(s);      // line 114, variable jj is declared in function above but not in this one.
    kk = atof1(s);      // line 115, double value returned by atof1() is converted to int
    kk = atof2(s);      // line 116, compiler uses created declaration to check and atof2() is assumed to return an int
    jj = atof1(s, 3);   // line 117, this use of atof1() does not match the declaration of atof1() in function xatoi() above.
    return (int)jj;     // line 118
}

上面的代码在Visual Studio 2015中生成以下警告和错误。

1>mldmodd.c(107): warning C4013: 'atof2' undefined; assuming extern returning int
1>mldmodd.c(114): error C2065: 'jj': undeclared identifier
1>mldmodd.c(114): warning C4244: '=': conversion from 'double' to 'int', possible loss of data
1>mldmodd.c(115): warning C4244: '=': conversion from 'double' to 'int', possible loss of data
1>mldmodd.c(117): error C2065: 'jj': undeclared identifier
1>mldmodd.c(117): warning C4020: 'atof1': too many actual parameters
1>mldmodd.c(117): warning C4244: '=': conversion from 'double' to 'int', possible loss of data
1>mldmodd.c(118): error C2065: 'jj': undeclared identifier
© www.soinside.com 2019 - 2024. All rights reserved.