Чтение онлайн

на главную - закладки

Жанры

Программирование. Принципы и практика использования C++ Исправленное издание
Шрифт:

Вы можете попросить включить проверку аргументов функций в языке С. Для этого достаточно объявить функцию с заданными типами аргументов (точно так же, как в языке С++). Такое объявление называется прототипом функции (function prototype). Тем не менее следует избегать объявлений, не задающих аргументы; они не являются прототипами функций и не включают механизм проверки типов.

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; /* не указан тип аргумента */

означающий, что функция

f
может принять любое количество аргументов любого типа, выглядит действительно странно. В ответ на это я изобрел новое обозначение, в котором понятие “ничего” указывалось явным образом с помощью ключевого слова
void
(void — слово из четырех букв, означающее “ничего”).

void f(void); /* не принимает никаких аргументов */

Впрочем, вскоре я об этом пожалел, потому что эта конструкция выглядит странно и при последовательной проверке типов аргументов является излишней. Что еще хуже, Деннис Ритчи (автор языка C) и Дуг Мак-Илрой (Doug McIlroy) (законодатель мод в Исследовательском центре компьютерных наук в компании Bell Labs (Bell Labs Computer Science Research Center; см. раздел 22.2.5) назвали это решение “отвратительным”. К сожалению, оно стало очень популярным среди программистов, работающих на языке С. Тем не менее не используйте его в программах на языке С++, в которых оно выглядит не только уродливо, но и является совершенно излишним.

В языке C есть альтернативное определение функции в стиле языка Algol-60, в котором типы параметров (не обязательно) указываются отдельно от их имен.

int old_style(p,b,x) char* p; char b;

{

/* ... */

}

Это определение “в старом стиле” предвосхищает конструкции языка С++ и не является прототипом. По умолчанию аргумент без объявленного типа считается аргументов типа
int
. Итак, параметр
x
является аргументом функции
old_style
, имеющим тип
int
. Мы можем вызвать функцию
old_style
следующим образом:

old_style; /* OK: пропущены все аргументы */

old_style("hello",'a',17); /* OK: все аргументы имеют правильный тип */

old_style(12,13,14); /* OK: 12 — неправильный тип */

/* но old_style может не использовать p */

Компилятор должен пропустить эти вызовы (но мы надеемся, что он предупредит о первом и третьем аргументах).

Мы рекомендуем придерживаться следующих правил проверки типов аргументов функций.

Поделиться:
Популярные книги

Блуждающие огни 4

Панченко Андрей Алексеевич
4. Блуждающие огни
Фантастика:
попаданцы
альтернативная история
5.00
рейтинг книги
Блуждающие огни 4

Я сделаю это сама

Кальк Салма
1. Магический XVIII век
Любовные романы:
любовно-фантастические романы
5.00
рейтинг книги
Я сделаю это сама

Флеш Рояль

Тоцка Тала
Детективы:
триллеры
7.11
рейтинг книги
Флеш Рояль

Боярышня Дуняша

Меллер Юлия Викторовна
1. Боярышня
Фантастика:
попаданцы
альтернативная история
5.00
рейтинг книги
Боярышня Дуняша

Газлайтер. Том 8

Володин Григорий
8. История Телепата
Фантастика:
попаданцы
альтернативная история
аниме
5.00
рейтинг книги
Газлайтер. Том 8

Леди для короля. Оборотная сторона короны

Воронцова Александра
3. Королевская охота
Любовные романы:
любовно-фантастические романы
5.00
рейтинг книги
Леди для короля. Оборотная сторона короны

На границе империй. Том 10. Часть 1

INDIGO
Вселенная EVE Online
Фантастика:
космическая фантастика
попаданцы
5.00
рейтинг книги
На границе империй. Том 10. Часть 1

Черный Маг Императора 5

Герда Александр
5. Черный маг императора
Фантастика:
юмористическое фэнтези
попаданцы
аниме
5.00
рейтинг книги
Черный Маг Императора 5

Невест так много. Дилогия

Завойчинская Милена
Невест так много
Любовные романы:
любовно-фантастические романы
7.62
рейтинг книги
Невест так много. Дилогия

Идеальный мир для Социопата 3

Сапфир Олег
3. Социопат
Фантастика:
боевая фантастика
6.17
рейтинг книги
Идеальный мир для Социопата 3

Повелитель механического легиона. Том VIII

Лисицин Евгений
8. Повелитель механического легиона
Фантастика:
технофэнтези
аниме
фэнтези
5.00
рейтинг книги
Повелитель механического легиона. Том VIII

Наследник павшего дома. Том I

Вайс Александр
1. Расколотый мир
Фантастика:
фэнтези
попаданцы
аниме
5.00
рейтинг книги
Наследник павшего дома. Том I

Крещение огнем

Сапковский Анджей
5. Ведьмак
Фантастика:
фэнтези
9.40
рейтинг книги
Крещение огнем

Камень Книга двенадцатая

Минин Станислав
12. Камень
Фантастика:
боевая фантастика
городское фэнтези
аниме
фэнтези
5.00
рейтинг книги
Камень Книга двенадцатая