Стивен Прата - Язык программирования C. Лекции и упражнения (6-е изд.) 2015

Тут можно читать онлайн Стивен Прата - Язык программирования C. Лекции и упражнения (6-е изд.) 2015 - бесплатно полную версию книги (целиком) без сокращений. Жанр: Прочая старинная литература, издательство Вильямс, год 0101. Здесь Вы можете читать полную версию (весь текст) онлайн без регистрации и SMS на сайте лучшей интернет библиотеки ЛибКинг или прочесть краткое содержание (суть), предисловие и аннотацию. Так же сможете купить и скачать торрент в электронном формате fb2, найти и слушать аудиокнигу на русском языке или узнать сколько частей в серии и всего страниц в публикации. Читателям доступно смотреть обложку, картинки, описание и отзывы (комментарии) о произведении.

Стивен Прата - Язык программирования C. Лекции и упражнения (6-е изд.) 2015 краткое содержание

Язык программирования C. Лекции и упражнения (6-е изд.) 2015 - описание и краткое содержание, автор Стивен Прата, читайте бесплатно онлайн на сайте электронной библиотеки LibKing.Ru

Язык программирования C. Лекции и упражнения (6-е изд.) 2015 - читать онлайн бесплатно полную версию (весь текст целиком)

Язык программирования C. Лекции и упражнения (6-е изд.) 2015 - читать книгу онлайн бесплатно, автор Стивен Прата
Тёмная тема
Сбросить

Интервал:

Закладка:

Сделать

int imin(int, int); /* объявление функции imin()*/ int evill, evill, lesser;

В любом случае основная задача заключается в том, чтобы обеспечить появление объявления функции до ее фактического применения.

338 Глава 9

В стандартной библиотеке ANSI С функции сгруппированы в семейства, каждое из которых имеет собственный заголовочный файл. Такие заголовочные файлы содержат среди прочего объявления функций в семействах. Например, заголовочный файл stdio.h включает объявления для стандартных библиотечных функций ввода-вывода, таких как printf() и scanf(). Заголовочный файл math.h содержит объявления для множества математических функций, например, объявление

double sqrt(double);

которое сообщает компилятору о том, что функция sqrt() принимает параметр типа double и возвращает значение типа double. Не путайте эти объявления с определениями. Объявление функции информирует компилятор о том, какой тин имеет функция, а определение функции предоставляет действительный код. Включение заголовочного файла math.h уведомляет компилятор о том, что возвращаемым типом sqrt() является double, но код для функции sqrt() находится в отдельном файле библиотечных функций.

Создание прототипов функций в ANSI С

Традиционная схема объявления функций, используемая до появления ANSI С, обладала тем недостатком, что предусматривала указание типа для возвращаемого значения функции, но не для ее аргументов. Давайте посмотрим, проблемы какого вида возникают в случае объявления функций по старой форме.

Следующее объявление, применяемое до выхода ANSI С, информирует компилятор о том, что функция imin() возвращает значение типа int:

int imin();

Однако оно ничего не говорит о количестве или типах аргументов этой функции. В результате, если функция imin() используется с некорректным количеством аргументов либо неподходящими их типами, то компилятор не сможет выявить ошибку.

Суть проблемы

Давайте рассмотрим несколько примеров, в которых задействована функция imax(), тесно связанная с imin(). В листинге 9.4 показана программа, в которой функция imax() объявляется устаревшим способом, а затем некорректно применяется.

Листинг 9.4. Программа misuse.с

Функции 339 В первом вызове printf не указан один аргумент функции imax а - фото 248

Функции 339

В первом вызове printf() не указан один аргумент функции imax(), а во втором вызове используются аргументы с плавающей запятой вместо целочисленных. Несмотря на эти ошибки, программа компилируется и запускается.

Вот пример вывода в случае применения XCode 4.6:

Наибольшим значением из 3 и 5 является 1606416656.

Наибольшим значением из 3 и 5 является 3886.

Запуск программы после компиляции с помощью gcc генерирует значения 1 359 379 472 и 1 359 377 160. Оба эти компилятора работают нормально, просто они становятся жертвами некорректного применения прототипов функций в программе.

Что происходит? Механизмы могут отличаться между системами, но вот что происходит в компьютере IBM PC или VAX. Вызывающая функция помещает аргументы во временную память, называемую стеком, и вызванная функция читает их оттуда. Оба эти процесса не скоординированы друг с другом. Вызывающая функция решает, какие типы передавать, на основе фактических аргументов в вызове, а вызванная функция читает значения, основываясь на типах своих формальных параметров. Таким образом, вызов imax(3) помещает в стек одно целочисленное значение. Когда функция imax() запускается, она читает из стека два целочисленных значений. Но в стек было помещено только одно значение, поэтому вторым прочитанным значением будет то, что случайно находилось в стеке в этот момент.

При втором использовании функции imax() ей передаются значения типа float. В результате в стек помещаются два значения типа double. (Вспомните, что при передаче в качестве аргумента тип float повышается до double.) В нашей системе это два 64-битных значения, так что в стек попадают 128 битов данных. Когда функция imax() читает из стека два значения типа int, она извлекает первые 64 бита, т.к. в нашей системе тип int занимает 32 бита. По случайному совпадению эти биты соответствовали двум целочисленным значениям, большим из которых оказалось 3 886.

Решение стандарта ANSI С

Подход к решению проблем с несоответствием аргументов, реализованный в стандарте ANSI С, предусматривает разрешение указывать в объявлении функции также и типы переменных. Результатом является прототип функции — объявление, в котором устанавливается возвращаемый тип, количество аргументов, а также их типы. Чтобы указать, что функция imax() требует два аргумента int, ее можно объявить с помощью одного из следующих прототипов:

int imax(int, int);

int imaxdnt а, int b);

В первой форме применяется список типов, разделенных запятыми. Во второй форме к типам добавлены имена переменных. Помните, что имена переменных являются фиктивными и не обязаны соответствовать именам, используемым в определении функции.

Располагая этой информацией, компилятор может проверить, совпадает ли вызов функции с прототипом. Указано ли правильное количество аргументов? Имеют ли они корректные типы? В случае несовпадения типов, когда оба типа являются числовыми, компилятор преобразует значения фактических аргументов в типы формальных параметров. Например, вызов imax (3.0, 5.0) становится imax (3, 5). Мы модифицировали код в листинге 9.4 для применения прототипа функции. Результат представлен в листинге 9.5.

340 глава 9

Листинг 9.5. Программа proto.с

Попытка компиляции программы из листинга 95 приводит к выдаче компилятором - фото 249

Попытка компиляции программы из листинга 9.5 приводит к выдаче компилятором сообщения об ошибке, указывающего на то, что вызов imax() содержит слишком мало параметров.

А что можно сказать об ошибках, связанных типами? Для их исследования мы заменили imax(3) вызовом imax(3, 5) и попробовали скомпилировать программу еще раз. На этот раз сообщения об ошибках не было, и мы запустили программу на выполнение. Ниже показан результирующий вывод:

Наибольшим значением из 3 и 5 является 5.

Наибольшим значением из 3 и 5 является 5.

Как и ожидалось, 3.0 и 5.0 во втором вызове были преобразованы в 3 и 5, чтобы функция могла должным образом обработать входные данные.

Хотя сообщения об ошибке отсутствовали, компилятор выдал предупреждение о том, что тип double был преобразован в тип int и возможна потеря данных. Например, вызов

imax(3.9, 5.4)

становится эквивалентным следующему вызову:

imax(3, 5)

Разница между сообщением об ошибке и предупреждением заключается в том, что ошибка предотвращает компиляции, а предупреждение — нет. Некоторые компиляторы выполняют такое приведение типа, не информируя вас. Причина связана с тем, что стандарт не требует вывода предупреждений. Однако многие компиляторы позволяют выбирать уровень выдачи предупреждений, который управляет многословностью компилятора при сообщении о предупреждениях.

Читать дальше
Тёмная тема
Сбросить

Интервал:

Закладка:

Сделать


Стивен Прата читать все книги автора по порядку

Стивен Прата - все книги автора в одном месте читать по порядку полные версии на сайте онлайн библиотеки LibKing.




Язык программирования C. Лекции и упражнения (6-е изд.) 2015 отзывы


Отзывы читателей о книге Язык программирования C. Лекции и упражнения (6-е изд.) 2015, автор: Стивен Прата. Читайте комментарии и мнения людей о произведении.


Понравилась книга? Поделитесь впечатлениями - оставьте Ваш отзыв или расскажите друзьям

Напишите свой комментарий
x