Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Программирование на C / C++ / Основы программирования на Си.doc
Скачиваний:
361
Добавлен:
02.05.2014
Размер:
1.3 Mб
Скачать

Локальные переменные

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

Нахождение адресов

В результате выполнения операции & определяется адрес ячейки памяти, которая соответствует переменной. Если age - имя переменной, то &age - ее адрес. Можно представить себе адрес как ячейку памяти, но можно рассматривать его и как метку, которая используется компилятором для идентификации переменной. Предположим, мы имеем оператор

age=105;

Пусть также адрес ячейки, где размещается переменная age - 15125. В результате выполнения оператора

printf("%d %d\n", age, &age);

получим 105 15125.

Указатели, первое знакомство

Указатель - некоторое символическое представление адреса. В описанном примере &age означает указатель на переменную age. Фактический адрес - это число, а символическое представление адреса &age является константой типа указатель. Адрес ячейки, отводимой переменной age, в процессе выполнения программы не меняется. В языке Си имеются и переменные типа указатель. Точно так же как значением переменной типа char является символ, а значением переменной типа int - целое число, значением переменной типа указатель служит адрес некоторой величины. Если мы дадим указателю имя ptr, то сможем написать, например, такой оператор:

ptr = &age;

/* присваивает адрес age переменной ptr */

Мы говорим в этом случае, что ptr указывает на age. Различие между двумя формами записи, ptr и &age, заключается в том, что ptr - это переменная, в то в то время как &age - константа. В случае необходимости мы можем сделать так, чтобы переменная ptr указывала на какой-нибудь другой объект:

ptr = &name;

/*ptr указывает на name, а не на age*/

Теперь значением переменной ptr является адрес переменной name.

Операция косвенной адресации *

Предположим, мы знаем, что в переменной ptr содержится ссылка на переменную name. Тогда для доступа к значению этой переменной можно воспользоваться операцией косвенной адресации *:

val = *ptr;

/* определение значения, на которое указывает ptr */

Последние два оператора, взятые вместе, эквивалентны следующему:

val = name;

Описание указателей

Примеры описания указателей:

int *pi; /*указатель на переменную типа целого*/

char *pc; /*указатель на символьную переменную*/

float *pf, *pg;

/* указатели на переменные с плавающей точкой*/

Спецификация типа задает тип переменной, на которую ссылается указатель, а символ звездочка (*) определяет саму переменную как указатель. Описание вида int *pi говорит , что pi - это указатель и что *pi - величина типа int.

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

function1(x);

происходит передача значения переменной x. Если же мы используем форму обращения

function2(&x);

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

function1(num)

int num;

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

function2(ptr)

int *ptr;

Подведем итоги по указателям

Когда за знаком & следует имя переменной, результатом операции является адрес указанной переменной.

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

Пример:

age = 105;

ptr =&age;/*указатель на age*/

val= *ptr;

Результатом выполнения этого фрагмента является присваивание значения 105 переменной val.

!

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

Типичные определения функции имеет следующий вид:

имя (список аргументов)

описание аргументов

тело функции

Наличие списка аргументов и описаний не обязательны. Переменные, отличные от аргументов, описываются внутри тела, которое заключается в фигурные скобки.

Аргументы используются для передачи значений из вызывающей программы в функцию. Использование ключевого слова return позволяет передавать в вызывающую программу одно значение из вызываемой функции. Обычно выполнение функции не оказывает никакого влияния на значения переменных вызывающей программы. Чтобы иметь возможность непосредственно изменять значения переменных вызывающей программы, необходимо использовать указатели в качестве аргументов. Это может оказаться необходимым в случае, если в вызывающую программу требуется передать более чем одно значение.

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