- •Линейные и разветвляющиеся вычислительные процессы Краткие теоретические сведения
- •Классификация данных
- •Декларирование объектов
- •Структура программы
- •Константы
- •Операции Операции выражения
- •Арифметические операции
- •Операция присваивания
- •Сокращенная запись операции присваивания
- •X##; - постфиксную.
- •Преобразование типов операндов арифметических операций
- •Операция приведения типа
- •Операции сравнения
- •Логические операции
- •Побитовые логические операции, операции над битами
- •Операция «,» (запятая)
- •Функции вывода информации
- •Функции ввода информации
- •Ввод - вывод потоками
- •Стандартные математические функции
- •Синтаксис операторов языка Си
- •Операция присваивания
- •Условные операторы
- •If (условие ) оператор1;
- •If (условие1) оператор1;
- •Условная операция "? :"
- •Оператор выбора switch
- •Программирование циклических вычислительных процессов
- •Циклические операторы while и do–while
- •Вложенные циклы
- •Программирование циклических вычислительных процессов с использованием одномерных массивов и строк Краткие теоретические сведения
- •Строки, как одномерные массивы символов
- •Указатели и операции над адресами
- •Операции над указателями (адресная арифметика)
- •Связь указателей и массивов
- •Пример 1: Упорядочить по алфавиту массив строк (не более 20) длиной не более 10 символов в каждой:
- •Многомерные массивы, динамическое распределение памяти Краткие теоретические сведения
- •Массивы указателей
- •Указатели на указатели
- •Динамическое размещение данных
- •Проверить, является ли введенная строка полиндромом (справа-налево читается также как и слева-направо).
- •Функции пользователя Краткие теоретические сведения
- •Декларация функций.
- •Вызов функции.
- •Изменение значений параметров.
- •Область действия переменных
- •Классы памяти.
- •Рекурсивные функции.
- •Операция typedef
- •Указатели на функции
- •Примеры работы с функциями
- •Программирование алгоритмов с использованием структур Краткие теоретические сведения Структуры
- •Декларация структурного типа данных
- •Создание структурных переменных
- •Обращение к полям структур
- •Вложенные структуры
- •Использование typedef
- •Массивы структур
- •Размещение структурных переменных в памяти
- •Пример на использование структур
Классы памяти.
В языке С/C++ каждая переменная принадлежит к одному из четырех классов памяти:
динамическая память, которая выделяется при вызове функции и освобождается при выходе из нее, атрибуты динамической памяти:
auto- автоматический;
register- регистровый.
статическая память, которая распределяется на этапе трансляции и заполняется по умолчанию нулями, атрибуты статической памяти:
внешний – extern;
статический – static.
Тип памяти указывается ключевым словом (auto, extern, static, register), стоящим перед спецификацией типа переменной. Например,
register int a;
По умолчанию переменная относится к классу auto и будет размещена в стеке.
Рекурсивные функции.
В языке С функции могут вызывать сами себя. В этом случае функция называется рекурсивной.
Пример рекурсивной функции – вычисление факториала числа n!=1*2*3*…*n:
int fac(int n)
{
int b;
if (n==1) return 1;
b=fac(n-1)*n;
return n;
}
Вызов функции в рекурсии не создает новую копию функции, а создает новые копии локальных переменных и параметров. Из рекурсивной функции надо предусмотреть выход, иначе система «зависает» через некоторое время работы с ней.
Операция typedef
Любому типу данных, как стандартному, так и определенному пользователем, можно задать новое имя с помощью операции
typedef <тип> <новое_имя>;
Введенный таким образом новый тип используется аналогично стандартным типам, например, введя пользовательские типы:
typedef int INT;
typedef char Mass_str[100];
декларации идентификаторов введенных типов имеют вид:
INT i, j; → две переменные iиjтипаint;
Mass_strstr[10]; → массивstrиз 10 строк по 100 символов.
Указатели на функции
В языке Си идентификатор функции является константным указателем на начало функции в оперативной памяти и не может быть значением переменной. Но имеется возможность декларировать указатели на функции с которыми можно обращаться как с переменными (например, можно создать массив, элементами которого будут указатели на функции).
Рассмотрим методику работы с указателями на функции:
1. Как и любой объект языка Си, указатель на функции необходимо декларировать. Формат объявления указателя на функции следующий:
тип (*переменная-указатель) (список параметров);
т.е. декларируется указатель, который можно устанавливать на функции, возвращающие результат указанного типа и имеют указанный список параметров. Наличие первых круглых скобок обязательно, так как без них –это декларация функции, которая возвращает указатель на результат своей работы указанного типа и имеет указанный список параметров. Например, объявление вида:
float (*p_f) (char, float);
говорит о том, что декларируется указатель p_f, который можно устанавливать на функции, возвращающие вещественный результат и имеющие два параметра: первый – символьного типа, а второй – вещественного типа.
2. Идентификатор функции является константным указателем, поэтому для того чтобы установить переменную-указатель на конкретную функцию, достаточно ей присвоить идентификатор этой функции:
переменная-указатель = имя_функции;
Например, имеется функция с прототипом
float f1(char, float);
тогда операция
p_f = f1;
установит указатель p_f на данную функцию.
3. Вызов функции после установки на нее указателя выглядит так:
(*переменная-указатель)(список аргументов);
или
переменная-указатель (список аргументов);
После таких действий кроме стандартного обращения к функции
имя_функции(список аргументов);
появляется еще два способа вызова функции:
(*переменная-указатель)(список аргументов);
или
переменная-указатель (список аргументов);
Последнее справедливо, так как p_f также является адресом начала функции в оперативной памяти. Для нашего примера к функции f1 можно обратиться следующими способами:
f1(‘z’, 1.5); // Обращение к функции по имени
(* p_f)(‘z’, 1.5); // Обращение к функции по указателю
p_f(‘z’, 1.5); // Обращение к функции по имени указателя
4. Пусть имеется вторая функция с прототипом:
float f2(char, float);
тогда, переустановив указатель p_f на эту функцию:
p_f = f2;
имеем опять три способа ее вызова:
f2(‘z’, 1.5); // по имени функции
(* p_f)(‘z’, 1.5); // по указателю на функцию
p_f(‘z’, 1.5); // по имени указателя на функцию
Основное назначение указателей на функции – это обеспечение возможности передачи идентификаторов функций в качестве параметров в функцию, которая реализует некоторый вычислительный процесс, используя формальное имя вызываемой функции.