Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

C_Kurs_Lekt / C_II_семестр / 11-2_ФУНКЦИИ_2

.pdf
Скачиваний:
10
Добавлен:
13.02.2016
Размер:
136.37 Кб
Скачать

Лысый Д.А. Основы программирования. Функции часть2

1

ФУНКЦИИ

Передача параметров

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

При передаче параметров по значению (в функцию передается копия значения параметра) любые изменения, выполняемые в функции над значением параметра, существуют только внутри самой функции. Когда функция завершается, значение переменной, переданной по значению, оказывается неизменным.

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

Многих случаях нужно иметь возможность изменять одну или несколько переменных в вызывающей функции или передавать функции указатель на большой объект данных, чтобы избежать издержек, связанных с передачей параметра по значению (так как в этом случае создается и потом передается копия объекта). Для этих целей в С существует возможность вызова функции по ссылке, используюя указатели и операцию косвенной адресации.

Ñпомощью указателя в вызываемую функцию можно передать адрес любого объекта из вызывающей программы. Обычно для этой цели применяется операция взятия адреса (&) к переменной, значение которой будет изменяться.

Ñпомощью выполняемого в тексте функции разыменования указателя (операция косвенной ад-

ресации * ) мы получаем доступ к адресуемому указателем объекту из вызывающей программы. Рассмотрим программы использующие вызовы по значению и по ссылке.

/ * Вычисление êóба числа с использованием вызова по значению * / #include <stdio.h>

int cube (int); main () {

int number = 5;

printf("The original value of number is %d\n", number); number = cube(number);

printf("The new value of number is %d\n", number); return 0;

}

int cube(int n) {

return n * n * n; /* возводим в êóб лоêальнóю переменнóю n */

}

The original value of number is 5

The new value of number is 125

Вычисление êóба переменной с вызовом по значению /* Вычисление êóба переменной при помощи вызова по ссылêе */ #include <stdio.h>

void cube(int *); main () {

int number = 5;

printf ("The original value of number is %d\n", number); cube(&number) ;

printf("The new value of number is %d\n", number); return 0;

}

void cube(int *nPtr) {

*nPtr = *nPtr * *nPtr * *nPtr; /* вычисление êóба переменной number фóнêции main */

}

The original value of number is 5 The new value of number is 125

Лысый Д.А. Основы программирования. Функции часть2

2

Последовательность выполнения вызова по значению

Последовательность выполнения вызова по ссылке

Использование модификатора const с указателями

Модификатор const дает возможность программисту сообщить компилятору о том, что значение указанной переменной не должно изменяться.

Существует шесть вариантов использования (или не использования) модификатора const с параметрами функции — две при передаче параметра по значению и четыре при передаче параметра по ссылке.

Если передаваемое функции значение не изменяется (или не должно быть изменено) в теле функции, оно должно объявляться с модификатором const, чтобы гарантировать невозможность даже случайного изменения.

Если происходит попытка изменить значение, которое было объявлено с модификатором const, компилятор перехватывает эту попытку и выдает либо предупреждение, либо сообщение об ошибке, в зависимости от того, какой .компилятор вы используете.

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

Самый высокий уровень доступа предоставляется не-константным указателем на не-константные данные. В этом случае данные могут изменяться через разыменование указателя, а сам указатель может изменяться и ссылаться на другие элементы данных. Объявление указателя — не константы на не константные данные не содержит ключевого слова const. Такой указатель (char *) мог бы использоваться, например, при передаче строки как параметра функции, в которой используются арифметические операции над указателем при обработке или изменении каждого отдельного символа в строке.

Пример:

/* Преобразование символов нижнеãо реãистра в символы верхнеãо */ /* реãистра с использованием óêазателя - не êонстанты на данные, */ /* êоторые моãóт модифицироваться */

#include <stdio.h>

void convertToUppercase(char *); main (){

char string[] = "characters";

printf("The string before conversion is: %s\n", stnng); convertToUppercase(string);

printf("The string after conversion is: %s\n", stnng); return 0;

}

void convertToUppercase(char *s) { while (*s != '\0' ) {

Лысый Д.А. Основы программирования. Функции часть2

3

if (*s >= 'a' && *s <= 'z')

*s -= 32; /* преобразование ê верхнемó реãистрó */

++s; /* óвеличение s для перехода ê следóющемó символó */

}

}

The string before conversion is: characters The string after conversion is: CHARACTERS

Указатель — не константа на данные-константы (const char *) — это указатель, который может изменяться и ссылаться на любой объект данных соответствующего типа, но элемент данных, на которые он указывает, не может изменяться. Такой указатель мог бы использоваться для передачи массива в ка- честве аргумента функции, которая обрабатывает каждый элемент массива и при этом не изменяет данные. Пример1:

/* Посимвольный вывод строêи, использóющий */

/* не-êонстантный óêазатель на êонстантные данные * / #include <stdio.h>

void printCharacters(const char *); main () {

char string[] = "print characters of а string"; printf("The string is:\n"); printCharacters(string);

putchar('\n'); return 0;

}

void printCharacters(const char *s) {

for ( ; *s != '\0'; s++) /* циêл не инициализирóется */ putchar (*s);

}

The string is:

print characters of à string

Пример2:

/* Попытêа изменения данных при помощи */ /* неêонстантноãо óêазателя на данные-êонстанты */

#include <stdio.h>

void f(const int *);

main ( ) {

 

int ó;

 

f(&y);

/* фóнêция f пытается выполнить изменение данных */

return 0; }

 

void f(const int *x) {

*x = 100; /* нельз модифицировать объеêт данных типа const */

}

Compiling FIG7_12.C:

Error FIG7_12.C 17: Cannot modify à const object Warning FIG7_12.C 18: Parameter 'x' is never used

Указатель-константа на не-константные данные (int * const) — указатель, который всегда указывает на одно и то же место в памяти, а расположенные там данные могут изменяться. Такой указатель назначается по умолчанию для имени массива. Имя массива является указателем-константой на начало массива. Ко всем элементам массива можно обращаться и изменять их, используя имя массива и индекс. Константный указатель на не-константные данные может использоваться для передачи массива как параметра функции, которая обращается к его элементам, используя только индекс массива. Указатели, которые объявляются с модификатором const, должны быть инициализированы при объявлении (если такой указатель является параметром функции, он инициализируется переданным функции значе- нием).

/*

Попытêа изменения óêазателя-êонстанты на */

/*

не-êонстантные данные

 

*/

I

#include

<stdio.h>

 

 

 

main() {

 

 

 

 

 

int

x, ó;

 

 

 

 

int * const ptr = &x;

 

 

 

 

ptr

=

&y;

 

 

 

 

return

0;

 

 

 

}

 

 

 

 

 

 

 

Compiling FIG7_13.Ñ:

 

 

 

 

Error FIG7_13.C 10: Cannot modify à const object

 

Warning FIG7_13.C 12:

'ptr'

is

assigned à value that is

 

never used Warning FIG7_13.C

12:

,'y' is declared but never used

Лысый Д.А. Основы программирования. Функции часть2

4

Минимальные права доступа предоставляет указатель-константа на константные данные. Такой указатель всегда указывает на то же самое место в памяти, а расположенные по этому адресу данные не могут модифицироваться. Этому варианту соответствует передача массива функции, которая только просматривает массив при помощи индекса и не изменяет его элементы. Пример, переменная-указатель ptr типа const int * const. Объявление читается справа налево и звучит так: «ptr — указатель-константа на целую константу».

/* Попытêа модифиêации óêазателя-êонстанты на */ /* данные-êонстанты */

#include <stdio.h> main () {

int x = 5, ó;

const int * const ptr = &x; *ptr = 7;

ptr = &y; return 0;

}

Compiling FIG7_14.C:

Error FIG7_14.C 10: Cannot modify à const object Error FIG7_14.C 11: Cannot modify à const object Warning FIG7_14.C 13: 'ptr' is assigned à value that is

never used Warning FIG7_14.C 13: ' y ' is declared but never used

Соседние файлы в папке C_II_семестр