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

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

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

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

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

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

Интервал:

Закладка:

Сделать

void ToUpper(char *); // преобразует строку в верхний регистр

Тин ToUpper() определен как “функция с параметром char * и возвращаемым типом void”. Вот как объявить указатель на функцию такого типа по имени pf:

void (*рf) (char *); // pf - указатель на функцию

Читая это объявление, вы видите, что первая пара круглых скобок связывает операцию * с pf, т.е. pf является указателем на функцию. Это делает (*рf) функцией, a (char * ) — списком ее параметров функции и void — возвращаемым типом. Вероятно, проще всего понять, как создано такое объявление — обратить внимание, что имя функции ToUpper в нем заменено выражением (*pf). Таким образом, если вы хотите объявить указатель на специфичный тип функции, можете объявить функцию этого типа и затем заменить имя функции выражением вида (*pf), получив в результате объявление указателя на функцию. Как упоминалось ранее, первые круглые скобки необходимы из-за правил, регламентирующих приоритеты операций. Если их отбросить, получится что-то совершенно другое:

void *pf(char *); // pf - функция, которая возвращает указатель

Совет

Чтобы объявить указатель на функцию конкретного типа, сначала объявите функцию желаемого типа и затем замените имя функции выражением в форме (*pf); после этого pf становится указателем на функцию данного типа.

Указателю на функцию можно присваивать адрес функции подходящего типа. В этом контексте для представления адреса функции может применяться ее имя:

void ToUpper(char *); void ToLower(char *); int round(double); void (*pf) (char *);

pf = ToUpper; // допустимо, ToUpper - адрес функции

pf = ToLower; // допустимо, ToLower - адрес функции

pf = round; // недопустимо, round - неподходящий тип функции

pf = ToLower(); // недопустимо, ToLower () не является адресом

Последнее присваивание также недопустимо, потому что нельзя использовать функцию void в операторе присваивания.

614 глава 14

Обратите внимание, что указатель pf может указывать на любую функцию, которая принимает аргумент char * и имеет возвращаемый тип void, но не на функции с другими характеристиками.

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

void ToUpper(char *); void ToLowertchar *); void (*pf) (char *); char mis[] = "Nina Metier"; pf = ToUpper;

(*pf)(mis); // применить ToUpper к mis (первый синтаксис) pf = ToLower;

pf(mis); // применить ToLower к mis (второй синтаксис)

Каждый подход выглядит логичным. Проанализируем первый подход: так как pf указывает на функцию ToUpper, то *pf — это функция ToUpper, поэтому выражение (*pf) (mis) аналогично ToUpper (mis). Чтобы убедиться в эквивалентности ToUpper и (*pf), достаточно взглянуть на объявления ToUpper и pf. Второй подход можно объяснить так: из-за того, что имя функции является указателем, указатель и имя функций можно применять взаимозаменяемо, следовательно, pf (mis) — это то же самое, что и ToLower (mis). Чтобы удостовериться в эквивалентности pf и ToLower, просто посмотрите на оператор присваивания для pf. Исторически сложилось так, что разработчики С и Unix в Bell Labs избрали первый подход, а разработчики, которые расширяли Unix в Беркли, приняли второй подход. Компилятор K&R С не разрешает вторую форму, но для поддержки совместимости с существующим кодом стандарт ANSI С принимает обе формы ((*pf) (mis) и pf (mis)) как эквивалентные. Последующие стандарты сохранили такой в высшей степени двойственный подход.

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

void show(void (* fp) (char *), char * str);

Он выглядит запутанным, но в нем объявляются два параметра, fp и str. Параметр fp — это указатель на функцию, a str — указатель на данные. Точнее, fp указывает на функцию, которая принимает параметр char * и имеет возвращаемый тип void, а str указывает на char. Таким образом, имея представленные выше объявления, можно делать вызовы функций вроде приведенных ниже:

show(ToLower, mis); /* show() использует функцию ToLower(): fp = ToLower */ show(pf, mis); /*show() использует функцию, указанную посредством pf: fp = pf */

Каким образом show() применяет переданный указатель на функцию? Для вызова этой функции в show() используется либо синтаксис fp(), либо синтаксис (* fр)():

void show(void (* fp)(char *), char * str)

{

(*fp)(str); /* применить выбранную функцию к str */ puts(str); /* отобразить результат */

}

Здесь функция show() сначала трансформирует строку str, применяя к ней функцию, на которую указывает fp, после чего отображает результирующую строку.

Структуры и другие формы данных 615

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

functionl(sqrt); /* передает адрес функции sqrt */

function2(sqrt(4.О)); /* передает возвращаемое значение функции sqrt */

Первый оператор передает адрес функции sqrt ( ) , и предположительно functionl() будет применять эту функцию в своем коде. Второй оператор сначала вызывает функцию sqrt() и затем передает возвращаемое значение (в этом случае 2.0) функции function2().

Для демонстрации основных идей в листинге 14.16 используется функция show() вместе с набором функций трансформации в качестве аргументов. В листинге также продемонстрировано несколько полезных приемов поддержки меню.

Листинг 14.16. Программа func_ptr.c

616 Глава 14 Структуры и другие формы данных 617 Ниже показаны результаты - фото 460

616 Глава 14

Структуры и другие формы данных 617 Ниже показаны результаты пробного - фото 461

Структуры и другие формы данных 617

Ниже показаны результаты пробного запуска Введите строку пустая строка - фото 462

Ниже показаны результаты пробного запуска:

Введите строку (пустая строка - выход из программы):

Does С make you feel loopy?

Введите выбранный вариант из меню: u) нижний регистр 1) верхний регистр

t) поменять местами регистры о) исходный регистр n) следующая строка t

dOES с MAKE YOU FEEL LOOPY?

Введите выбранный вариант из меню: u) нижний регистр 1) верхний регистр

t) поменять местами регистры о) исходный регистр n) следующая строка l

does с make you feel loopy?

Введите выбранный вариант из меню: u) нижний регистр 1) верхний регистр

t) поменять местами регистры о) исходный регистр n) следующая строка n

Введите строку (пустая строка - выход из программы) :

Программа завершена.

Обратите внимание, что функции ToUpper(), ToLower(), Transpose() и Dummy() имеют тот же самый тип, поэтому все они могут быть присвоены указателю pfun. В этой программе в качестве аргумента для show() применяется pfun, но можно также указывать непосредственно любое из имен четырех функций, как в show (Transpose, copy).

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

Интервал:

Закладка:

Сделать


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

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




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


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


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

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