ВУЗ: Не указан
Категория: Не указан
Дисциплина: Не указана
Добавлен: 13.12.2020
Просмотров: 4250
Скачиваний: 28
Часть I. Язык программирования С
86
void f(int* const a, int n, int m)
{
int i;
for (i = 0; i < n * m; ++i)
++a[i];
}
В этом случае используется тот факт, что элементы статических
массивов хранятся в памяти последовательно. Вызов этой функ-
ции будет выглядеть следующим образом:
int a[2][2] = {1, 2, 3, 4};
f(&a[0][0], 2, 2);
6.6. Указатели на функции
(функторы)
Язык программирования C позволяет определять указатели на
функции, которые имеют следующий вид:
спецификатор_типа (*имя_указателя)(список_параметров)
Например, указатель на функцию, которая возвращает значение
типа
int
и имеет два параметра типа
int
, может быть объявлен
как:
int (*fp)(int x, int y);
Указателю на функцию можно присвоить адреса различных
функций, которые имеют такие же типы возвращаемого значения
и параметров. Например, если определена функция:
int add(int x, int y) { return x + y; }
То ее адрес можно присвоить указателю
fp
следующим образом:
fp = &add;
Учитывая, что имя функции является адресом этой функции в
памяти, указателю на функцию можно просто присвоить имя
функции. То есть:
fp = add;
Глава 6. Функции
87
Так как указателю на функцию могут присваиваться адреса раз-
личных функций при условии совпадения типа параметров и типа
возвращаемого значения, то указатель на функцию часто назы-
вают
функтором
.
Вызвать функцию через указатель можно двумя способами:
(*имя_указателя)(список_аргументов);
имя_указателя(список_аргументов).
Представляется, что первый способ более наглядный, т. к. явно
указывает, что функция вызывается через указатель.
В листинге 6.3 приведена программа, в которой функции сложе-
ния и вычитания двух чисел вызываются через указатель.
Листинг 6.3. Вызов функций через указатель
#include <stdio.h>
int add(int x, int y) { return x + y; }
int sub(int x, int y) { return x - y; }
int main(void)
{
int (*p)(int, int);
p = add;
printf("1 + 2 = %d\n", (*p)(1, 2));
p = sub;
printf("1 - 2 = %d\n", p(1, 2));
return 0;
}
Тип указателя на функцию может также использоваться как тип
возвращаемого функцией значения и тип параметра функции.
Например, в листинге 6.4 приведена функция
foo
, которая полу-
чает в качестве параметра указатель на функцию и просто воз-
вращает его.
Листинг 6.4. Использование типа указателя на функцию
как типа возвращаемого значения и типа параметра функции
#include <stdio.h>
int (*foo(int (*p)(int)))(int) { return p; }
Часть I. Язык программирования С
88
int inc(int x) { return ++x; }
int dec(int x) { return --x; }
int main(void)
{
int (*f) (int); /* указатель на функцию */
f = foo(inc); /* устанавливаем указатель на inc */
printf("2 + 1 = %d\n", (*f)(2));
f = foo(dec); /* устанавливаем указатель на dec */
printf("2 - 1 = %d\n", (*f)(2));
return 0;
}
В заключение этого раздела отметим, что над указателями на
функции нельзя выполнять никаких арифметических операторов.
Г Л А В А
7
Структура программы
на языке С
7.1. Область видимости
идентификатора
Если переменная объявлена вне какого-либо блока, то такая пе-
ременная называется
глобальной
. В противном случае переменная
называется
локальной
.
Областью видимости идентификатора
называется наибольшая
область программы, в которой можно сослаться на этот иденти-
фикатор. Существуют четыре типа областей видимости:
блок;
функция;
прототип функции;
исходный файл.
Глобальные переменные видимы внутри исходного файла, в ко-
тором они определены.
Локальные переменные видимы только внутри блока или функ-
ции, в которой они определены. Локальная переменная скрывает
любую переменную с тем же именем, объявленную вне этого
блока.
В листинге 7.1 приведен пример, демонстрирующий сокрытие
имен переменных.
Часть I. Язык программирования С
90
Листинг 7.1. Сокрытие имен переменных
#include <stdio.h>
int n = 1;
int main(void)
{
printf("n = %d\n", n); /* n = 1 */
{
int n = 2;
printf("n = %d\n", n); /* n = 2 */
{
n = 3;
printf("n = %d\n", n); /* n = 3 */
}
}
return 0;
}
Параметры функции видны только внутри функции или объявле-
ния этой функции.
Функции всегда определяются вне какого-либо блока. Областью
видимости функции является исходный файл, в котором эта
функция определена.
7.2. Время существования
переменных и функций
Время существования переменной
или
функции
определяется как
время, в течение которого эта переменная или функция хранится
в памяти компьютера.
Глобальные переменные существуют в течение всего времени
выполнения программы и хранятся в фиксированной области па-
мяти программы, которая задается во время ее компиляции. Если
глобальная переменная не проинициализирована, то компилятор
устанавливает ее значение в ноль.
Память для локальных переменных выделяется динамически во
время исполнения программы. При вызове функции или входе в