#include
, будет включен механизм проверки типов. Однако в больших программах на это трудно рассчитывать. Вследствие этого в большинстве компиляторов языка С существуют опции, предусматривающие выдачу предупреждений о вызовах необъявленных функций: воспользуйтесь ими. Кроме того, с первых дней существования языка C появились программы, с помощью которых можно выявлять все возможные проблемы, связанные непротиворечивостью типов. Обычно они называются lint
.
Вы можете попросить включить проверку аргументов функций в языке С. Для этого достаточно объявить функцию с заданными типами аргументов (точно так же, как в языке С++). Такое объявление называется
int g(double); /* прототип — как в языке С ++ */
int h(); /* не прототип — типы аргументов не указаны */
void my_fct()
{
g(); /* ошибка: пропущен аргумент */
g("asdf"); /* ошибка: неправильный тип аргумента */
g(2); /* OK: 2 преобразуется в 2.0 */
g(2,3); /* ошибка: один аргумент лишний */
h(); /* Компилятор допускает! Результат непредсказуем */
h("asdf"); /* Компилятор допускает! Результат непредсказуем */
h(2); /* Компилятор допускает! Результат непредсказуем */
h(2,3); /* Компилятор допускает! Результат непредсказуем */
}
h()
не указан тип аргумента. Это не означает, что функция h()
не получает ни одного аргумента; это значит: принимает любой набор аргументов и надеется, что это набор при вызове окажется правильным. И снова отметим, что хороший компилятор предупредит об этой проблеме, а программа lint
перехватит ее.
Существует специальный набор правил, регламентирующих преобразование аргументов, если в области видимости нет прототипа функции. Например, переменные типов char
и short
преобразуются в переменные типа int
, а переменные типа float
— в переменные типа double
. Если вы хотите знать, скажем, что произойдет с переменной типа long
, загляните в хороший учебник по языку С. Наша рекомендация проста: не вызывайте функций, не имеющих прототипов.
Обратите внимание на то, что, хотя компилятор допускает передачу аргументов неправильного типа, например параметр типа char*
вместо параметра типа int, использование таких аргументов приводит к ошибкам. Как сказал Деннис Ритчи: “С — это язык программирования со строгим контролем типов и слабой проверкой”.
27.2.3. Определения функций
Можете определять функции точно так же, как в языке С++. Эти определения являются прототипами функций.
double square(double d)
{
return d*d;
}
void ff()
{
double x = square(2); /* OK: переводим 2 в 2.0 и вызываем */
double y = square(); /* пропущен аргумент */
double y = square("Hello"); /* ошибка: неправильный тип
аргументов */
double y = square(2,3); /* ошибка: слишком много аргументов */
}
Определение функции без аргументов не является прототипом функции.
void f() { /* что-то делает */ }
void g()
{
f(2); /* OK в языке C; ошибка в языке C++ */
}
Код
void f(); /* не указан тип аргумента */