- •Битовые операции
- •Битовые логические операции
- •Битовые операции сдвига
- •Логические операции
- •Битовые операции
- •Логические операции
- •Логический тип
- •Преобразование типов данных
- •Символьный тип
- •Целочисленный тип
- •Вещественный тип
- •Оператор цикла while
- •Оператор цикла for
- •Оператор цикла do while
- •Программирование вложенных циклов
- •Переприсваивание
- •Объединение строк
- •Escape-знаки
- •Точные строки: символ @
- •Преобразование строк в другие типы
- •Объединения
- •Основные понятия
- •7.2. Определение функции
- •Вызов функции
- •Передача данных по значению
- •Передача данных по адресу
- •Передача данных по ссылке
- •Передача одномерного массива в функцию
- •Вызовы с переменным числом аргументов
- •Определение значений по умолчанию
- •Организация работы с файлами средствами c
- •Файловый ввод-вывод с использованием потоков
- •Инкапсуляция
- •Наследование
- •Полиморфизм
- •Массивы указателей
- •Предварительная инициализация параметров функции
- •Динамические массивы ограниченного размера и их объём[]
- •Макроопределение - директива #define
- •Структура библиотеки
- •Бщее описание[править | править исходный текст]
- •Неструктурная обработка исключений[
- •Структурная обработка исключений[
Передача данных по адресу
По адресу в функцию всегда передаются массивы (рассмотрим это в следующих темах). Для массива это вообще единственный способ передачи данных в языках С/С++. Так же по адресу можно передать те простые объекты, которые являются выходными данными (или входными и выходными одновременно).
В случае передачи данных по адресу фактический параметр может быть только переменной (константа или выражение не имеют адреса!).
Вернёмся к предыдущему примеру.
Пример 3. Даны два числа, хранящиеся в переменных a и b. Используя подпрограмму, выполнить обмен содержимого ячеек этих переменных.
Данные передадим по адресу. Они будут в этой задаче и входными, и выходными данными. Для контроля изменения содержимого ячеек памяти будем выводить на экран монитора промежуточные данные.
Возможный вариант реализации программы:
#include <iostream>
using namespace std;
void Obmen(double *x, double *y);
int main()
{
double a = 2.5, b = 3.1;
cout << "Do Obmen: a=" << a << " b=" << b << endl;
Obmen(&a, &b);
cout << "Posle Obmen: a=" << a << " b=" << b << endl;
return 0;
}
void Obmen(double *x, double *y)
{
double c;
cout << "Function Obmen start:\n *x=" << *x << " *y=" << *y << endl;
c = *x;
*x = *y;
*y = c;
cout << "Function Obmen end:\n *x=" << *x << " *y=" << *y << endl;
}
Результаты выполнения программы:
Do Obmen: a=2.5 b=3.1
Function Obmen start:
*x=2.5 *y=3.1
Function Obmen end:
*x=3.1 *y=2.5
Posle Obmen: a=3.1 b=2.5
Печать на экране монитора наглядно показывает, что обмен произведён, и исходные переменные теперь имеют новые значения, т.е. передача данных по адресу действительно позволяет вернуть в вызывающую функцию результат работы вызываемой подпрограммы.
Как это работает? Рассмотрим данный вопрос подробнее, используя пример с обменом данных. Для наглядности приведём рисунок:
В вызывающей функции (в нашем случае — в main()) вычисляются адреса объектов, передаваемых по адресу ( у нас — адреса переменных a и b. Пусть это будут числа 1000 и 1008), и затем эти адреса копируются в ячейки памяти — указатели, память под которые выделена в функции Obmen() (это x и y). Зная адрес переменной, например, адрес переменной a, который теперь хранится в указателе x, можно, пользуясь операцией разыменование, не только прочитать, но и изменить значение исходной переменной.
Ни какой реальной передачи данных (в смысле копирования) из подпрограммы Obmen() назад в main() не делается. Мы на самом деле через указатели работаем с исходными объектами! Поэтому после выхода из функции Obmen() имеем изменённые переменные a и b (если быть точнее, переменные изменятся ещё до выхода из функции,то есть в момент перестановки в самой функции Obmen()).
Передача данных по ссылке
Это ещё один из способов вернуть результат работы функции через список параметров. Напомним, что применяется только для С++. В языке С такого варианта нет.
При передаче данных по ссылке в функцию, куда передаются данные, создаются синонимы исходных объектов. Поэтому работа в подпрограмме ведётся именно с исходными объектами. Если в подпрограмме ссылочная переменная изменит значение, то это сразу отразится на исходной переменной.
В вызывающей функции параметр, передаваемый по ссылке, может быть только простой переменной любого известного типа.
Вернёмся снова к примеру обмена, только данные передадим по ссылке.
Пример 4. Даны два числа, хранящиеся в переменных a и b. Используя подпрограмму, выполнить обмен содержимого ячеек этих переменных.
Возможный вариант реализации программы:
#include <iostream>
using namespace std;
void Obmen(double &x, double &y);
int main()
{
double a = 2.5, b = 3.1;
cout << "Do Obmen: a=" << a << " b=" << b << endl;
Obmen(a, b);
cout << "Posle Obmen: a=" << a << " b=" << b << endl;
return 0;
}
void Obmen(double &x, double &y)
{
double c;
cout << "Function Obmen start:\n x=" << x << " y=" << y << endl;
c = x;
x = y;
y = c;
cout << "Function Obmen end:\n x=" << x << " y=" << y << endl;
}
Результаты выполнения программы:
Do Obmen: a=2.5 b=3.1
Function Obmen start:
x=2.5 y=3.1
Function Obmen end:
x=3.1 y=2.5
Posle Obmen: a=3.1 b=2.5
Результаты, выводимые на экран монитора, подтверждают правильность работы.
Обратите внимание на то, что для объекта, передаваемого по ссылке, в списке формальных параметров указывается значок & перед именем переменной (работаем с ссылкой на объект), а далее в теле подпрограммы используется просто имя этой переменной. При вызове в списке фактических параметров задаётся имя нужной переменной.
Для простых объектов передача данных по ссылке предпочтительнее, чем передача по адресу, так как в этом случае текст функции проще, легче читается, не требуется выполнять операции разыменования.
К недостатку способа (передача данных по ссылке) можно отнести то, что по вызову функции нельзя понять, что параметр передаётся именно по ссылке, а не по значению, и как следствие, этот параметр скорее всего изменяется функцией. Чтобы не было сомнений, всегда смотрите на запись прототипов функций, использованных в программе. Прототипы всегда доступны, даже если сами функции имеются только в виде объектных модулей.
21Передача массивов в функцию. Указатель на функцию.
