Книга: Язык программирования Си. Издание 3-е, исправленное
5.2 Указатели и аргументы функций
5.2 Указатели и аргументы функций
Поскольку в Си функции в качестве своих аргументов получают значения параметров, нет прямой возможности, находясь в вызванной функции, изменить переменную вызывающей функции. В программе сортировки нам понадобилась функция swap, меняющая местами два неупорядоченных элемента. Однако недостаточно написать
swap(a, b);
где функция swap определена следующим образом:
void swap(int х, int у) /* НЕВЕРНО */
{
int temp;
temp = х;
x = y;
у = temp;
}
Поскольку swap получает лишь копии переменных a и b, она не может повлиять на переменные a и b той программы, которая к ней обратилась. Чтобы получить желаемый эффект, вызывающей программе надо передать указатели на те значения, которые должны быть изменены:
swap(&a, &b);
Так как оператор & получает адрес переменной, &a есть указатель на a. В самой же функции swap параметры должны быть объявлены как указатели, при этом доступ к значениям параметров будет осуществляться косвенно.
void swap(int *px, int *py) /* перестановка *px и *py */
{
int temp;
temp = *рх;
*рх = *py;
*ру = temp;
}
Графически это выглядит следующим образом: в вызывающей программе:
Аргументы-указатели позволяют функции осуществлять доступ к объектам вызвавшей ее программы и дают возможность изменить эти объекты. Рассмотрим, например, функцию getint, которая осуществляет ввод в свободном формате одного целого числа и его перевод из текстового представления в значение типа int. Функция getint должна возвращать значение полученного числа или сигнализировать значением EOF о конце файла, если входной поток исчерпан. Эти значения должны возвращаться по разным каналам, так как нельзя рассчитывать на то, что полученное в результате перевода число никогда не совпадет с EOF.
Одно из решений состоит в том, чтобы getint выдавала характеристику состояния файла (исчерпан или не исчерпан) в качестве результата, а значение самого числа помещала согласно указателю, переданному ей в виде аргумента. Похожая схема действует и в программе scanf, которую мы рассмотрим в параграфе 7.4. Показанный ниже цикл заполняет некоторый массив целыми числами, полученными с помощью getint.
int n, array[SIZE], getint (int *);
for (n = 0; n ‹ SIZE && getint (&array[n]) != EOF; n++)
;
Результат каждого очередного обращения к getint посылается в array[n], и n увеличивается на единицу. Заметим, и это существенно, что функции getint передается адрес элемента array[n]. Если этого не сделать, у getint не будет способа вернуть в вызывающую программу переведенное целое число.
В предлагаемом нами варианте функция getint возвращает EOF по концу файла; нуль, если следующие вводимые символы не представляют собою числа; и положительное значение, если введенные символы представляют собой число.
#include ‹ctype.h›
int getch (void);
void ungetch (int);
/* getint: читает следующее целое из ввода в *pn */
int getint(int *pn)
{
int c, sign;
while (isspace(c = getch()))
; /* пропуск символов-разделителей */
if (!isdigit(c) && c != EOF && c != '+ '&& c != '-') {
ungetch (c); /* не число */
return 0;
}
sign = (c == '-') ? -1 : 1;
if (с == '+' || с == '-')
с = getch();
for (*pn = 0; isdigit(c); c = getch())
*pn = 10 * *pn + (c -'0');
*pn *= sign;
if (c != EOF)
ungetch(c);
return c;
}
Везде в getint под *pn подразумевается обычная переменная типа int. Функция ungetch вместе с getch (параграф 4.3) включена в программу, чтобы обеспечить возможность отослать назад лишний прочитанный символ.
Упражнение 5.1. Функция getint написана так, что знаки - или +, за которыми не следует цифра, она понимает как "правильное" представление нуля. Скорректируйте программу таким образом, чтобы в подобных случаях она возвращала прочитанный знак назад во ввод.
Упражнение 5.2. Напишите функцию getfloat - аналог getint для чисел с плавающей точкой. Какой тип будет иметь результирующее значение, задаваемое функцией getfloat?
- 5.1 Указатели и адреса
- 5.2 Указатели и аргументы функций
- 5.3 Указатели и массивы
- 5.4 Адресная арифметика
- 5.5 Символьные указатели функции
- 5.6 Массивы указателей, указатели на указатели
- 5.7 Многомерные массивы
- 5.8 Инициализация массивов указателей
- 5.9 Указатели против многомерных массивов
- 5.10 Аргументы командной строки
- 5.11 Указатели на функции
- 5.12 Сложные объявления
- Фактические аргументы
- Глава 5. Указатели и массивы
- Аргументы функции в Python
- Пересмотр функций клиента
- Вызовы функций
- 9.1.6.1. Использование функций POSIX: wait() и waitpid()
- Урок 6.4. Расчеты с использованием функций и имен ячеек
- Мастер функций
- Практическая работа 46. Выполнение расчетов с использованием Мастера функций
- Практическая работа 47. Расчеты с использованием логических функций
- Семейство функций exec()
- Необязательные аргументы