1. Краткие
теоретические сведения
1.1. Функции
Функцию
в Си можно рассматривать:
· как один из производных типов данных
(наряду с массивами и указателями);
· как минимальный исполняемый модуль
программы (подпрограмму).
Все функции имеют единый формат определения:
<тип><имя_функции>(<список_формальных_параметров>) , где
<тело_функции> , где
<тип>
- либо void, если функция не возвращает значения,
либо тип возвращаемого функцией значения;
<имя_функции> - либо main для
основной функции, либо произвольный идентификатор, не совпадающий со служебными
словами и именами других объектов программы;
<список_формальных_параметров> - либо пустой ( ), либо список, каждый элемент которого имеет вид:
<обозначение_типа><имя_параметра>
Например:
(int k )
(char i, char j, int z)
<тело_функции> -
это часть определения функции, заключенная в фигурные скобки
{ }.Тело функции может быть либо составным оператором, либо блоком.
Определения функций не могут быть вложенными.
Для передачи результата из функции в
вызывающую функцию используется оператор return. Он
может использоваться в двух формах:
1) return; - завершает функцию
возвращающую никакого значения (т. е.
перед именем функции указан тип void)
2) return <выражение>; - возвращает
значение выражения, выражение должно иметь тип, указанный перед именем функции.
3)
Если программист не пишет оператор return явно, то компилятор автоматически дописывает return в конец тела функции перед закрывающей фигурной
скобкой}.
Пример:
int op (char c, int x, int y)
{
switch c
{
case ‘+’ : return x+y;
case ‘-’ : return
x-y;
case ‘*’ : return
x*y;
case ‘/’ : return
x/y;
default: cout<<“\nОперация не определена”;return 0;
}
}
Вызов функции осуществляется следующим образом:
<обозначение
функции>(<список фактических параметров>); где
<обозначение
функции> - либо имя функции, либо указатель на функцию;
<список
фактических параметров> - список выражений, количество которых равно числу
формальных параметров функции. Между формальными и фактическими параметрами
должно быть соответствие по типам.
Например:
c = op ( ‘+’,
5 ,4 );
Синтаксис Си предусматривает только один
способ передачи параметров - передача по значению (т. е. изменить значения
параметров внутри функции нельзя). Но
существует возможность косвенно изменить значения переменных передаваемых в
виде параметров: с помощью указателя в вызываемую функцию можно передать адрес
любого объекта из вызывающей программы. Если указатель разыменовать,
то получится значение, записанное по этому адресу.
Пример
(ошибка!!!):
1)
//описание
функции для обмена переменных а и b
void change (int a,int b)
{
int r;
r = a; a = b; b = r;
}
// вызов функции
change(a, b);
Обмена не произойдет, т. к. результат
не будет передан в вызывающую программу.
2)
void change (int *a,int *b)
{
int r;
r = *a; *a = *b;
*b = r;
}
// вызов функции
change(&a,
&b);
При
вызове передаются адреса, по которым находятся значения и выполняется обмен
значений, которые находятся по этим адресам.
1.2. Массивы и строки как
параметры функций
Если в качестве параметра функции используется
обозначение массива, то на самом деле в функцию передается адрес первого
элемента массива.
Пример:
//вычисление
суммы элементов массива
//вариант 1
int sum (int n, int a[] )
{
int i,int s=0;
for( i=0; i<n; i++
)
s+=a[i]
return s;
}
void main()
{
int a[]={ 3, 5, 7,
9, 11, 13, 15 };
int s = sum(
cout<<s;
}
//вариант 2
int sum (int n, int *a)
{
for(int i=0, s=0; i<n; s+=*(a+i),i++ );
return s;
}
void main()
{
int a[]={ 3, 5, 7, 9, 11, 13, 15 };
int
s = sum(
cout<<s;
}
Строки в качестве фактических параметров
могут быть определены либо как одномерные массивы типа char[],
либо как указатели типа char*. В отличие от обычных массивов в этом случае
нет необходимости явно указывать длину строки.