- •Глава 7. Указатели
- •Основные понятия
- •Объявление указателей
- •Операция адреса
- •Операция разыменования
- •Инициализация указателей
- •Адресная арифметика
- •Функции и указатели
- •Передача аргументов в функцию по указателю
- •Указатель в качестве возвращаемого значения функции
- •Некоторые особенности использования указателей Нулевые указатели
- •Указатели на тип void
- •Указатели на константу и константные указатели
Функции и указатели
Функции в языке С++ имеют ряд ограничений. Во-первых, если аргументы передаются в функцию по значению, то изменения, внесенные в аргументы во время выполнения функции, не влияют на значения аргументов, которые передаются в функцию. Во-вторых, возвращать функция может только одно значение скалярного типа. Преодолеть эти два ограничения можно путем использования ссылок или указателей.
Из главы 5 мы уже узнали, как изменить значения аргументов, передаваемых в функцию, используя ссылки (см. примеры 5.7, 5.8). Однако, поскольку многие программисты С++ используют указатели для изменения значений аргументов, необходимо знать и такой вариант программирования.
Передача аргументов в функцию по указателю
Рассмотрим, как изменить значения аргументов, передаваемых в функцию, используя указатели:
для изменения значения аргумента функция должна знать адрес соответствующего аргумента;
используя операцию адреса (&), программа может передать адрес аргумента в функцию при её вызове;
когда функция получает адрес аргумента, она должна объявить соответствующий параметр как указатель (предваряя имя параметра звездочкой);
если функции требуется использовать значение, на которое ссылается (указывает) указатель, функция должна предварять имя параметра-указателя звездочкой, т.е. операцией разыменования (*).
Например, в следующем фрагменте программы параметром функции является указатель на тип int, а значением аргумента, передаваемого программой в функцию – адрес переменной:
…
int main(){
int y = 5; fun(&y);
cout<<y<<endl; // 6
…
}
void fun(int * x){
(*x)++; cout<<*x<<endl; // 6
}
В Примере 7.1. аргументы функции change() передаются по указателю (версия функции change() для случая передачи аргументов по ссылке была рассмотрена в 5-ой главе, Пример 5.7).
// Пример 7.1. Обмен значений двух переменных оформить в виде
// функции. change() Аргументы в функцию передавать по указателю.
#include <iostream>
using namespace std;
void change(int*, int*);
int main(){
int a = 10, b = 5;
change(&a, &b);
cout<<"Posle perestanovki(main): ";
cout<<"a = "<<a<<", b = "<<b<<endl; // a = 5, b = 10
system("pause");
}
void change(int * x, int * y){
cout<< "Do perestanovki(change): ";
cout<<"x = "<<*x<<", y = "<<*y<<endl; // x = 10, y = 5
int z = *x; *x = *y; *y = z;
cout<< "Posle perestanovki(change):\n";
cout<<"x = "<<*x<<", y = "<<*y<<endl; // x = 5, y = 10
}
При передаче в функцию аргумента по указателю функция получает адрес этого аргумента и может применить операцию разыменования (*), получая, таким образом, доступ непосредственно к переменной, находящейся по этому адресу (что и позволяет её изменять).
// Пример 7.2. Расположить значения переменных а, в, с в порядке
// возрастания, используя функцию перестановки переменных change().
// Аргументы в функцию передавать по указателю.
#include <iostream>
using namespace std;
void change(int *, int *);
int main(){
int a, b, c;
cout<<"Vvedi a, b, c = "; cin>>a>>b>>c;
if(a > b) change(&a, &b);
if(b > c) change(&b, &c);
if(a > b) change(&a, &b);
cout<<" a = " << a << " b = "<<b<<" c = "<<c<<endl;
system("pause");
}
void change(int * x, int * y){
int temp;
temp = *x; *x = *y; *y = temp;
}
При передаче указателей в качестве аргументов функции предполагается, что эти аргументы должны изменяться внутри функции и эти изменения следует передать в вызывающую программу. Если это не так, лучше передавать аргументы по значению или использовать указатели на константы. Это защитит программу от несанкционированного изменения данных функцией.