在C

时间:2016-09-14 03:49:03

标签: c

我正在阅读KR C书,我面对一个我不理解的功能定义。它是qsort()函数的第87页。它在swap()函数中声明qsort()函数:

void qsort(args)
{
 ...
 void swap(arguments);
 ...
 swap(a,b);
}

void swap(arguments){
...
}

不能在函数之外声明swap()函数吗?为什么在qsort()函数内声明它?

1 个答案:

答案 0 :(得分:8)

我想您正在阅读K& R C编程语言,也许正在阅读ANSI C的第二版? https://hassanolity.files.wordpress.com/2013/11/the_c_programming_language_2.pdf上有PDF,第87页有使用快速排序算法的递归讨论。

请参阅此维基百科主题,比较和对比各种C标准https://en.wikipedia.org/wiki/ANSI_C

K& RC书籍是旧式C,因为第二版版权是1988年。那里有很多好材料,但它需要从旧式的角度阅读,C标准自ANSI C以来已经改变。有关编译器应该声明为错误和警告的更好的规范。 ANSI C中完全可以接受的东西在现代C标准中已不再可接受。通过加强C编程语言规范并提供一些额外的关键字和语法,许多工作已经尝试通过编译器提供更好的静态检查。

应该有swap()的前向声明,或者函数的定义及其源代码应该在实际使用函数之前出现。这允许C编译器根据其声明或定义检查函数的使用情况,以检查可能的使用错误。

但是使用C编程语言如果在定义或声明之前使用函数,通常会从Visual Studio 2013 warning C4013: 'swap' undefined; assuming extern returning int收到警告,例如此警告。

有些编译器,clanggcc的最新版本以及Visual Studio 2015已经开始实现C11。有些编译器提供了其他选项来改进警告和/或将某些警告变成错误。

例如,如果我在文件testit.c中有以下源代码(注意C源代码的.c文件扩展名)并使用Visual Studio 2013使用警告级别4进行编译,我将收到一组警告但没有错误。 Visual Studio使用C的标准和规则将其编译为C源,即使对于相同的语法,它也比C ++的标准和规则更宽松。

我编译了这个源的两个不同版本,一个是第2行的前向声明注释掉的,另一个是未注释的。请注意警告,Visual Studio的C编译器允许在没有前向声明的情况下使用函数。

请注意,当第二行中的前向声明在第二次运行中取消注释时,会出现关于在函数范围内放置函数的前向声明的警告:warning C4210: nonstandard extension used : function given file scope

另请注意,通过第二次运行中提供的前向声明,编译器能够识别可能的使用错误并发出警告,并在一种情况下发出实际错误。

请注意,参数的数量在第一次和第二次编译中都有所不同,但只有在第二次编译中,前向声明未注释且可供编译器使用,我们是否会看到有关额外参数的警告。

int func1() {                        // line 1
//  int swap(int a, int b);          // line 2, forward declaration for function swap

    int j = swap(1, 2);

    return 0;
}

int func2() {                         // line 9
    struct {
        int a;
        int b;
        int c;
    } mm = { 0 };

    int k = swap(4, 5, 8);             // line 16

    float ff = swap(4.0, 5.0, 8.0);    // line 18

    int k2 = swap(mm, 2, 3);           // line 20

    return 1;
}

int swap(int a, int b) {               // line 25
    return a + b;
}

警告是:

1>------ Build started: Project: ConsoleApplication3, Configuration: Debug Win32 ------
1>  testit.c
1>c:\users\projects\consoleapplication3\testit.c(4): warning C4013: 'swap' undefined; assuming extern returning int
1>c:\users\projects\consoleapplication3\testit.c(4): warning C4189: 'j' : local variable is initialized but not referenced
1>c:\users\projects\consoleapplication3\testit.c(18): warning C4244: 'initializing' : conversion from 'int' to 'float', possible loss of data
1>c:\users\projects\consoleapplication3\testit.c(16): warning C4189: 'k' : local variable is initialized but not referenced
1>c:\users\projects\consoleapplication3\testit.c(20): warning C4189: 'k2' : local variable is initialized but not referenced
1>c:\users\projects\consoleapplication3\testit.c(18): warning C4189: 'ff' : local variable is initialized but not referenced
1>  ConsoleApplication3.vcxproj -> C:\Users\Projects\Debug\ConsoleApplication3.exe

如果我取消注释函数swap()的前向声明,我会看到以下编译器输出的警告以及错误:

1>------ Build started: Project: ConsoleApplication3, Configuration: Debug Win32 ------
1>  testit.c
1>c:\users\projects\consoleapplication3\testit.c(2): warning C4210: nonstandard extension used : function given file scope
1>c:\users\projects\consoleapplication3\testit.c(4): warning C4189: 'j' : local variable is initialized but not referenced
1>c:\users\projects\consoleapplication3\testit.c(16): warning C4020: 'swap' : too many actual parameters
1>c:\users\projects\consoleapplication3\testit.c(18): warning C4244: 'function' : conversion from 'double' to 'int', possible loss of data
1>c:\users\projects\consoleapplication3\testit.c(18): warning C4020: 'swap' : too many actual parameters
1>c:\users\projects\consoleapplication3\testit.c(18): warning C4244: 'initializing' : conversion from 'int' to 'float', possible loss of data
1>c:\users\projects\consoleapplication3\testit.c(20): error C2440: 'function' : cannot convert from '' to 'int'
1>c:\users\projects\consoleapplication3\testit.c(20): warning C4024: 'swap' : different types for formal and actual parameter 1
1>c:\users\projects\consoleapplication3\testit.c(20): warning C4020: 'swap' : too many actual parameters

现在C ++编程语言不同,不允许这种松散。这就是为什么虽然C ++与C共享历史,但C ++是一种不同的相关语言。

如果我将相同的源复制到文件testit2.cpp然后编译我会看到不同的错误。

首先将swap()的前瞻性声明注释掉。

1>  testit2.cpp
1>c:\users\projects\consoleapplication3\testit2.cpp(4): error C3861: 'swap': identifier not found
1>c:\users\projects\consoleapplication3\testit2.cpp(16): error C3861: 'swap': identifier not found
1>c:\users\projects\consoleapplication3\testit2.cpp(18): error C3861: 'swap': identifier not found
1>c:\users\projects\consoleapplication3\testit2.cpp(20): error C3861: 'swap': identifier not found

再次声明前进声明。

1>  testit2.cpp
1>c:\users\projects\consoleapplication3\testit2.cpp(4): warning C4189: 'j' : local variable is initialized but not referenced
1>c:\users\projects\consoleapplication3\testit2.cpp(16): error C3861: 'swap': identifier not found
1>c:\users\projects\consoleapplication3\testit2.cpp(18): error C3861: 'swap': identifier not found
1>c:\users\projects\consoleapplication3\testit2.cpp(20): error C3861: 'swap': identifier not found

最后,如果我将swap()的前向声明从函数func1()的范围移到文件范围中,使它现在为第1行,那么我将看到以下不同的错误:

1>  testit2.cpp
1>c:\users\projects\consoleapplication3\testit2.cpp(4): warning C4189: 'j' : local variable is initialized but not referenced
1>c:\users\projects\consoleapplication3\testit2.cpp(16): error C2660: 'swap' : function does not take 3 arguments
1>c:\users\projects\consoleapplication3\testit2.cpp(18): error C2660: 'swap' : function does not take 3 arguments
1>c:\users\projects\consoleapplication3\testit2.cpp(20): error C2660: 'swap' : function does not take 3 arguments