
- •«Национальный исследовательский томский политехнический университет»
- •Матричные исчисления с использованием функций пользователя
- •Понятие функции
- •Определение пользовательской функции
- •Передача значений в функцию: фактические и формальные параметры
- •Локальные и глобальные переменные
- •Возврат результатов из функции
- •Return выражение;
- •Адреса и указатели
- •Размещение функций в файле
- •Массивы как параметры функций
- •Двумерный массив как параметр функции
- •Краткие выводы
-
Локальные и глобальные переменные
Переменные, объявленные в функции, являются её внутренними переменными и "не известны" вызывающей функции. Аналогично переменные, объявленные в вызывающей функции, не известны внутри других функций. Переменные, известные только одной функции, а именно той, которая их содержит, называются локальными переменными; они действуют только в пределах этой функции. В случае, когда в двух или больше функциях встречаются одинаковые имена переменных, они будут соответствовать совершенно различным ячейкам памяти.
Кроме этого, в языке Си допускается наличие переменных, известных нескольким функциям. Такие переменные называются глобальными. Переменная является глобальной, если она описана вне тела какой-либо функции. Обычно глобальные переменные описываются в самом начале, сразу после команд препроцессора.
ВНИМАНИЕ! Значение глобальной переменной можно изменить внутри любой функции, поэтому с ними надо обращаться осторожно и не злоупотреблять их использованием.
Пример:
#include <stdio.h>
float a[10][20]; //массив описан как глобальный
void my_func()
{
float b[10]; //массив описан как локальный
b[0] = 0;
a[0][0] = 0;
...
}
void main ()
{
my_fuc();
printf("a00 = %f\n",a[0][0]); //правильно, т.к. используется
//элемент массива а, описанного глобально
printf("b0 = %f\n",b[0]); //неправильно, т.к. массив b здесь просто
// "неизвестен" (он известен только внутри функции my_funk()!)
}
-
Возврат результатов из функции
В том случае, когда результатом выполнения функции является одна величина простого типа, для возврата этого результата можно воспользоваться оператором return (см. Пример 2 из п. 9.2.2). В этом случае функция должны иметь тот же тип, что и значение, которое она возвращают в качестве результата. Его структура выглядит следующим образом:
Return выражение;
где в качестве выражения может выступать как отдельная переменная, так и выражение (арифметическое или логическое), которое сначала будет вычислено, а затем этот результат будет возвращен в вызывающую функцию.
Примеры:
return x;
return a[0]+a[1]*x;
return z < w;
Таким образом, с помощью оператора return в вызывающую функцию можно передать только одну величину.
Так как в языке Си при обращении к функции через параметры передаются конкретные значения соответствующих аргументов, то вернуть полученные значение через аргументы, перечисленные в заголовке функции, просто так не удастся.
Если в вызывающую функцию требуется передать (вернуть) более чем одно значение, необходимо в качестве аргументов использовать указатели.
-
Адреса и указатели
Вообще говоря, указатель – это некоторое символическое представление адреса переменной. В том случае, если переменная описана, например, как p, то использование в программе p означает использование значения переменной (например, 3.14), а &p означает "указатель на переменную p", т.е. это – "адрес переменной p". Фактический адрес – это число (например, 32550). Тогда выполнение оператора p = 2.5; можно "перевести" как фразу "разместить число 2.5 по адресу 32550".
Адрес ячейки, отводимой переменной, в процессе выполнения программы не меняется, поэтому символическое представление адреса &p является константой типа указатель (вспомните параметры функции scanf()!).
В языке Си имеются и переменные типа указатель. Точно так же, как значением переменной типа float является вещественное число, значением переменной типа указатель служит адрес некоторой величины.
При описании переменной как указателя необходимо задать, на переменную какого типа ссылается данный указатель:
тип *имя;
Символ звездочка (*) определяет саму переменную как указатель (вспомните описание переменной, связанной с файлом).
Например:
float *p;
int *k;
Тогда p – это указатель (его величина – это адрес), а *p – величина типа float., которую можно использовать, например, в арифметических выражениях:
*p = 3.1;
float a = *p + 1;
Так как значение адреса переменной не изменяется, то если в качестве аргумента передать функции адрес переменной, то внутри этой функции можно изменить значение этой переменной, и это новое значение будет известно после выполнения и в вызывающей функции.
Пример:
void obmen(int* a, int* b)
{
int temp;
temp = *a;
*a = *b;
*b = temp;
}
void main()
{
int x, y;
x = 2;
y = 3;
printf("здесь x = %d, а y = %d\n", x, y);
obmen( &x, &y );
printf("теперь x = %d, а y = %d\n", x, y);
}
В приведенном примере функции obmen() передаются в качестве аргументов адреса локальных переменных x и y, а сама функция obmen() занимается обменом значений, расположенных по этим адресам. Указатели позволяют обойти тот факт, что что переменные функции obmen() являются локальными. Они дают возможность этой функции "добраться" до функции main() и изменить величины описанных в ней объектов.