Определение функции с аргументом
Определение нашей функции начинается с двух строк:
space (number);
int number;
Первая строка информирует компилятор о том, что у функции space () имеется аргумент и что его имя number .Вторая строка — описание, указывающее компилятору, что аргумент number имеет тип int . Аргумент описывается перед фигурной скобкой, которая отмечает начало тела функции. Можно объединить эти две строки в одну:
space (int number);
Переменная number называется «формальным» аргументом. Фактически это новая переменная, и в памяти компьютера для нее должна быть выделена отдельная ячейка.
Вызов функции с аргументом
Переменной number присваивается значение фактического аргумента при вызове функции. Например, случай использования функции space ( ):
space (25):
Фактический аргумент здесь 25, и эта величина присваивается формальному аргументу — переменной number , т. е, вызов функции оказывает следующее действие:
number = 25;
Формальный аргумент — переменная в вызываемой программе, а фактический аргумент — конкретное значение, присвоенное этой переменной вызывающей программой. Фактический аргумент может быть константой, переменной или даже более сложным выражением. Независимо от типа фактического аргумента он вначале вычисляется, а затем его величина передается функции.
Локальные переменные
Переменные в функции являются ее внутренними переменными и «не известны» вызывающей функции. Аналогично переменные вызывающей функции не известны вызываемой функции. Вот почему для связи с ней, т. с. для передачи значений в нее и из нее, мы пользуемся аргументами и оператором return . Переменные, известные только одной функции, а именно той, которая их содержит, называются «локальными» переменными. Переменные, известные нескольким функциям, называются «глобальными».Если мы используем одно и то же имя для переменных в двух различных функциях, компилятор «считает» их разными переменными. Мы можем показать это, используя операцию &.
|
|
Глобальные переменные
Глобальные переменные видны во всех функциях, где не описаны локальные переменные с теми же именами, поэтому использовать их для передачи данных между функциями очень легко. Тем не менее, это не рекомендуется.
Нахождение адресов: операция &
В результате выполнения операции & определяется адрес ячейки памяти, которая соответствует переменной. Еслиp — имя переменной, то & p — ее адрес. Можно представить себе адрес как ячейку памяти, но можно рассматривать его и как метку, которая используется компьютером для идентификации переменной. Мы имеем оператор
p = 24;
Пусть также адрес ячейки, где размещается переменная p — 12126. Тогда в результате выполнения оператора
|
|
printf ("%d %d \n", p, &p);
получим 24 12126
Воспользуемся указанной выше операцией для проверки того, в каких ячейках хранятся значения переменных, принадлежащих разным функциям, но имеющих одно и то же имя.
// контроль адресов
main() {
int a = 2, b = 5;
printf(" В main( ), a = %d и &a = %u\n", a, &a);
printf(" В main( ), b = %d и &b = %u\n", b, &b);
fun(a);
}
fun(b)
int b;
{
int a = 10;
printf(" В fun( ), a = %d и &a = %u\n", a, &a);
printf(" В fun( ), b = %d и &b = %u\n", b, &b);
}
Мы воспользовались форматом % u (целое без знака) для вывода на печать адресов на тот случай, если их величины превысят максимально возможное значение числа типа int . В нашей вычислительной системе результат работы этой программы выглядит так:
В main( ), a = 2 и &a = 56002
В main( ), b = 5 и &b = 56004
В fun ( ), a = 10 и &a = 55944
В fun ( ), b = 2 и &b = 56000
О чем это говорит? Во-первых, две переменные a имеют различные адреса. То же самое верно и относительно переменных b . Компьютер рассматривает их как четыре разные переменные. Во-вторых, при вызове fun ( a )величина (2) фактического аргумента ( a из main ( )) передается формальному аргументу ( b из fun ( )). Было передано только значение переменной. Адреса двух переменных ( a в main ( ) и b в fun ( )) остаются различными. В языке Си аргументы передаются по значению.
|
|
Возвращаемое значение
Механизм возврата из функции в вызвавшую ее функцию реализуется оператором
return [выражение];
Функция может содержать несколько операторов return (если это необходимо алгоритму функции). Если функция описана как void, выражение не указывается. Оператор return можно опускать для функции типа void, если возврат из нее происходит перед закрывающейся фигурной скобкой, и для функции main.
Параметры функции
Механизм параметров – основной способ обмена информацией между вызываемой функцией и вызывающей функцией. Параметры, перечисленные в заголовке описания функции, называются формальными параметрами, или просто параметрами, а записанные в операторе вызова – фактическими параметрами, или аргументами.
Существуют 2 способа передачи параметров в функцию: по значению и по адресу.
При передаче по значению в стек заносятся копии значений аргументов, и операторы функции работают с этими копиями. Доступа к исходным значениям параметров у функции нет, а, следовательно, нет и возможности их изменить.
При передаче по адресу в стек заносятся копии адресов аргументов, а функция осуществляет доступ к ячейкам памяти по этим адресам и может изменять исходные значения аргументов.
|
|
Пример передачи параметров в функцию по значению.
// обмен1
main() {
int x = 5, у = 10;
printf(" Вначале x = %d и у = %d\n", x, у);
change(x, у);
printf(" Теперь x = %d и у = %d\n", x, у);
}
change(int u, int v) {
int temp;
temp = u;
u = v;
v = temp;
}
Результаты будут выглядеть следующим образом:
Вначале х = 5 и у = 1 0
Теперь х = 5 и у = 10
Функции change () и main () используют различные переменные, поэтому обмен значениями между переменными u и v не оказывает никакого влияния на х и у.
Ниже приводится программа, в которой указатели служат средством, обеспечивающим правильную работ у функции, которая осуществляет обмен значениями переменных.
// обмен2
main() {
int х=5, у = 10;
printf(" Вначале x = %d и у = %d\n", x, у);
change(&x, &у); //передача адресов функции
printf(" Теперь x = %d и у = %d\n", x, у);
}change(int *u, int *v) { // u и v являются указателями
int temp;
temp = *u; //temp присваивается значение, на которое указывает u
*u = *v;
*v = temp;
}
Результат:
Вначале х = 5 и у = 10.
Теперь х = 10 и у = 5.
Во-первых, теперь вызов функции выглядит следующим образом:
change (&x, &y);
Вместо передачи значении х и у мы передаем их адреса. Это означает, что формальные аргументы u и v при обращении будут заменены адресами и, следовательно, они должны быть описаны как указатели. Поскольку x и у — целого типа, u и v являются указателями на переменные целого типа, и мы вводим описание int * u , int * v для описания формальных параметров функции change . Далее в теле функции оператор описания int temp используется с целью резервирования памяти. Мы хотим поместить значение переменной х в переменную temp , поэтому пишем temp = * u ; Мы не должны писать, например, так:
temp = u; // неправильно
поскольку при этом происходит запоминание адреса переменной х, а не ее значения; мы же пытаемся осуществить обмен значениями, а не адресами.
Дата добавления: 2020-04-25; просмотров: 154; Мы поможем в написании вашей работы! |
Мы поможем в написании ваших работ!