Я полагаю, что вы читаете язык программирования программирования K & R C и, возможно, второе издание с ANSI C? Существует PDF на https://hassanolity.files.wordpress.com/2013/11/the_c_programming_language_2.pdf и на странице 87 обсуждается рекурсия с использованием алгоритма быстрой сортировки.
Смотрите эту Википедии тему сравнения и сопоставления различных стандартов C https://en.wikipedia.org/wiki/ANSI_C
В K & RC книги старый стиль C как Second Edition авторское право 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 закомментировал и один с ним был раскопан. Обратите внимание на предупреждения о том, что компилятор C Visual Studio позволяет использовать функцию без прямого объявления.
Уведомление о том, что во втором прогоне декларируется прямое объявление в строке 2, есть предупреждение о том, что нужно добавить объявление вперед для функции в пределах области функций: 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
Вы не можете использовать функцию, которая не объявлена. Не имеет особого значения, когда вы объявляете это, пока вы его объявляете, прежде чем использовать его, и объявление находится в области видимости. – Tibrogargan
Разве это не область, ограниченная внутри блока, где определено? В этом случае 'swap()' действует только в 'qsort()' function – Arash
@Arash Да. И в части файла после его определения тоже, конечно. Потому что объявление является объявлением. – hyde