我正在阅读KR C书,我面对一个我不理解的功能定义。它是qsort()
函数的第87页。它在swap()
函数中声明qsort()
函数:
void qsort(args)
{
...
void swap(arguments);
...
swap(a,b);
}
void swap(arguments){
...
}
不能在函数之外声明swap()
函数吗?为什么在qsort()
函数内声明它?
答案 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
收到警告,例如此警告。
有些编译器,clang
和gcc
的最新版本以及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