Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Лекция 04.doc
Скачиваний:
1
Добавлен:
01.07.2025
Размер:
83.46 Кб
Скачать

Лекция N 4

Параметр функции - указатель

Указатель можно использовать в качестве параметра. Ниже приведен пример функции для обмена значений двух аргументов.

Void swap(int * arg1, int * arg2)

{

int tmp=*arg1;

*arg1=*arg2;

*arg2=tmp;

}

Void main(void)

{

int x=1,y=2;

swap(&x,&y); // в качестве фактических параметров используются

// адреса переменных x и y

// . . .

}

При каждом вызове функции в стеке создается новая копия ее формальных параметров и автоматических (локальных) переменных. Занятая ими память после

выхода из функции освобождается, поэтому некорректно возвращать указатель на

локальную переменную. Содержимое памяти, на которую настроен такой указатель,

затем может измениться непредсказуемым образом:

int* f()

{

int local = 1;

// ...

return &local; // ошибка

}

Ссылки, использование ссылок в качестве параметров

Ссылка является псевдонимом или альтернативным именем переменной. Ссылки реализуются с помощью скрытного использования указателей. Наиболее часто ссылки применяются для определения параметров и возвращаемых значений функций.

int x, i=1;

int &r=i; // теперь r ссылается на i

x=r; // x=1

r=2; // i=2

При определении ссылки она должна быть сразу же инициализирована . Инициализация ссылки есть нечто совершенно отличное от присваивания ей. Вопреки ожиданиям, ни одна операция на ссылку не действует. Например:

int i=0;

int &r=i;

r++; // i увеличивается на единицу, поскольку r “ссылается” на i

Ниже приведен пример предыдущей функции с использованием ссылок в качестве параметров.

Void swap(int & arg1, int & arg2)

{

int tmp=arg1;

arg1=arg2;

arg2=tmp;

}

Void main(void)

{

int x=1,y=2;

swap(x,y); // в качестве фактических параметров используются

// . . . ссылки на переменные x и y

}

Таким образом параметры в функцию незаметно для нас передаются через их адреса.

Ссылкой может быть возвращаемое значение функции. Например:

Int &move(int&I)

{

return i;

}

Void main(void)

{

int i=10;

move(i)=100;

printf("%d\n",i); // печатается 100

}

Некорректно возвращать ссылку на локальную переменную, так как она

перестает существовать при выходе из функции, например:

int& f()

{

int local = 1;

// ...

return local; // ошибка

}

К счастью, транслятор предупреждает о том, что возвращается ссылка на

локальную переменную. Вот другой пример:

Int& f() { return 1; } // ошибка

Использование const при описании функции.

Void f(const large& arg)

{

// подчеркивается, что значение "arg" внутри функции не меняется

}

Если в описании параметра ссылки const не указано, то это рассматривается как намерение изменять передаваемый объект:

Void g(large& arg); // считается, что в g() arg будет меняться

Точно так же, описание параметра, являющегося указателем, со спецификацией const говорит о том, что указываемый объект не будет изменяться в вызываемой функции. Например:

// из <string.h>

extern int strlen(const char*);

extern char* strcpy(char* to, const char* from);

extern int strcmp(const char*, const char*);

Объект может быть объявлен константой при обращении к нему с помощью

указателя, и в то же время быть изменяемым, если обращаться к нему другим

способом. Особенно это удобно использовать для параметров функции. Описав

параметр-указатель функции как const, мы запрещаем изменять в ней указываемый

объект.

Может быть вполне разумным и даже полезным описание функции с типом

возвращаемого значения const:

const char* peek(int i) // вернуть указатель на строку-константу

{

return hidden[i];

}

Приведенную функцию можно было бы использовать для передачи строки,

защищенной от изменения, в другую программу, где она будет читаться.

Параметр функции - массив

Если в качестве параметра функции указан массив, а как мы уже знаем

имя массива компилятор трактует как будто это указатель, то в функцию

передается указатель на его первый элемент. Поэтому функция работает с элементами оригинального массива, указатель на который загружается в стек.

Например: