С поддерживает предварительное объявление (декларацию) функций, которое также созданием называется прототипом. Предварительное объявление позволяет перечислить список функций в начале исходной программы. Такой список предлагает удобный способ указания того, какие функции будут использованы в программе. Кроме того, использование прототипов заранее уведомляет компилятор о типах возвращаемых значений и формальных параметров различных функций. После объявления функций можно размещать их определения в любом порядке и не волноваться по поводу ошибок компиляции, которые происходят, когда функция вызывается перед объявлением или определением. Общий синтаксис объявления для функции:
[ <Класс_памяти>] <Тип_возвращаемого_значения> <имя> ([ <Список_типов_параметров >]);
Классы памяти для функций: extern и static. По умолчанию – extern .
Каждая функция имеет <тип_возвращаемого_значения>, который указывается перед названием (<именем>) функции. <Список_параметров> следует за названием функции и заключается в круглые скобки.
Точка с запятой в конце необходима для объявления функции, но не нужна в определении функции. Имена формальных параметров могут отсутствовать или не опадать с именами в определении функции, но типы должны совпадать обязательно. По умолчанию тип возвращаемого значения int.
Пример объявления функции:
dauble summa(float a, float b); // два параметра типа float, возвращается
// значение типа dauble
С использует специальный тип void, чтобы указать, что функция не требует параметров или не возвращает значение. Использование оператора return в void -функции не требуется.
Примеры объявлений функций:
upDate(); // без параметров, // возвращается int void (void); // без параметров // getPrint | void releesDate(int fop);// один // параметр void reseedType(float Seed); // один // параметр |
|
Синтаксис определения функций в С
Синтаксис определения функций в С имеет следующий вид:
[<Класс_памяти>] <Тип возвращаемго_значения> <Имя> ([<Список_объявлений_формальных_параметров>])
{[// - объявления переменных (декларации);]
// - операторы;
[return <возвращаемое_значение_заданного_типа>;]
}
Функция возвращает результат своей работы, используя оператор return, который обычно появляется в конце тела функции. Однако, функция может иметь больше одного оператора return.
<Список_объявлений_формальных_параметров> функции может отсутствовать (void), содержать одно или больше объявлений формальных параметров, соответствующих (аргументов)данной функции. Параметры в списке разделяются запятой и имеют синтаксис:
[модификатор]<тип_параметра><имя>
В качестве модификаторов могут использоваться следующие ключевые слова const, near, face, huge.
Примеры определений функций, объявленных ранее
dauble summa(float x, float y)// требу- // ет два параметра {return x+y; // возвращаемое значение преобразуется к типу dauble } | void getPrint(void) //без параметров // и возвращаемого значения {printf (n \” Пример\n”); } // returnотсутствует |
Функция summa() имеет два параметра и тип возвращаемого значения dauble. Функция getPrint() не имеет параметров и возвращаемого значения.
Если функция объявлена с ключевым словом inline, то компилятор заменяет любой вызов inline - функции копией её тела, приведенного в определении.
Пример inline - функции: inline long square(int nNum) {return nNum*nNum; } | В примере определена inline - функция square (), которая возвращает квадрат параметра nNumтипаint. |
|
Использование локальных и глобальных переменных в функциях.
Вызов функции
В любойфункции можно объявлять локальные константы и переменные. Область действия локальных констант и переменных ограничена телом функции-хозяина. Никакая функция не может непосредственно получить доступ к локальным константам и переменным другой функции. Существует два класса памяти локальных переменных: register и auto, которые указываются перед типом переменных. Локальные переменные создаются каждый раз, когда функция начинает выполняться, а когда функция завершает работу, система устраняет локальные переменные.
В отличие от автоматических переменных, статические переменные (с классом памяти static) сохраняют своё значение между вызовами функции. Эта особенность позволяет в функциях использовать значения, вычисленные при предыдущем вызове. Статическая переменная инициализируется один раз при первом вызове функции явно или по умолчанию нулевым значением. Инициализация статических переменных позволяет, например, функции-хозяину определить, выполняется ли она впервые.
Пример статических переменных, объявленных в функции
int doCalc() {static int index1=2; static float my_index; // другие объявления // операторы return …; } | В примере объявлена и явно инициализирована статическая переменная index1, а также инициализирована неявно переменная my_index(по умолчанию равна 0).Эти переменные сохраняют свои значения между вызовами функции doCalc (). |
Пример
|
/* ЗАНЯТИЕ N 7
Выполнил студент группы......... Петров Ю.В.
Объявление и определение функций. Применение функций:
передача переменных в функцию по значению, по адресу
и по ссылке, возврат значений из функции. Области
видимости переменных, примеры операций.
Выбор функции - по номеру с помощью оператора switch*/
#include <stdio.h>
#include <conio.h>
#include <math.h>
float glob=2.5;
float Fx0(float a, float b, float c) //Определение функции
{ return --b/(2*a)*(++c); }
//Fx0-Передача параметров и возврат по значению
float* Fx1(float, float, float); //Объявление функции
//Fx1-Передача параметров по значению, возврат указателя
float& Fx2(float, float, float); //Объявление функции
//Fx2-Передача параметров по значению, возврат ccылки
//Передача параметров по значению, последнего по адресу
void changex0(float, float, float, float *);
//Передача и изменение параметров по адресу
void changex1(float *, float *, float *, float *);
//Передача изменение параметров по ccылке
void changex2(float &, float &, float &, float &);
void main()
{ float a1,b1,c1,x1;
float* px=&x1;
float& sx=x1;
char diskr;
clrscr();
printf(" Введитe значения переменных: а, b, c: ");
scanf("%f %f %f", &a1, &b1, &c1);
printf("Введитe номер функции (0...5),\
6 или ESC-конец расчета: ");
vvod1: diskr=getche();
switch (diskr)
{case '0': x1=Fx0(a1,b1,c1); break;
case '1': px=Fx1(a1,b1,c1); printf("\nglob= \
%6.3f *px= %6.3f", glob, *px); break;
case '2': sx=Fx2(a1,b1,c1); printf("\nglob= \
%6.3f sx= %6.3f", glob, sx); break;
case '3': changex0(a1, b1, c1,&x1); break;
case '4': changex1(&a1,&b1,&c1,&x1); break;
case '5': changex2(a1, b1, c1, x1); break;
case '6':case 27: goto end;
default:printf("\nВне диапазона, введите другой \
номер функции (0...5) ");
goto vvod1;
}
printf("\nРезультат: a1= %5.3f b1= %5.3f c1= %5.3f \
x1= %5.3f\n",a1,b1,c1,x1);
printf("Введите другой номер функции: ");
goto vvod1;
end:;
}
float* Fx1(float a, float b, float c) //Определение функции N 1
{ float*pf;
*pf=glob+(--b)/(2*a)*(++c);
//printf("\nglob= %6.3f *pf= %6.3f",glob,*pf);
return pf;
}
float& Fx2(float a, float b, float c) //Определение функции N 2
{ float& sf=glob;
sf=(--b-sqrt(abs(++c)))/(4*++a);
glob+=5; //printf("\nglob= %6.3f sf= %6.3f ",glob,sf);
return sf;
}
void changex0(float a, float b, float c, float *d) //N 3
{ *d=pow(b,2)-4*--a*++c; }
void changex1(float *a, float *b, float *c, float *d) //N 4
{++*a; ++*b++; ++*c; *d+=*a+*b+*c; }
void changex2(float &a, float &b, float &c, float &d) //N 5
{ a+=2; b+=2; c+=2; d-=a+b+c; }
/* Введитe значения переменных: а, b, c: 3 4 5
Введитe номер функции (0...5), 6 или ESC-конец расчета: 0
Результат: a1= 3.000 b1= 4.000 c1= 5.000 x1= 3.000
Введите другой номер функции: 1
glob= 2.500 *px= 5.500
Результат: a1= 3.000 b1= 4.000 c1= 5.000 x1= 5.500
Введите другой номер функции: 2
glob= 5.034 sx= 5.034
Результат: a1= 3.000 b1= 4.000 c1= 5.000 x1= 5.034
Введите другой номер функции: 3
Результат: a1= 3.000 b1= 4.000 c1= 5.000 x1=-32.000
Введите другой номер функции: 4
Результат: a1= 4.000 b1= 5.000 c1= 6.000 x1=-18.000
Введите другой номер функции: 5
Результат: a1= 6.000 b1= 7.000 c1= 8.000 x1=-39.000
Введите другой номер функции: 8
Вне диапазона, введите другой номер функции (0...5) 6 */
Ход работы
1 Изучить теоретические сведения.
2 В соответствии с индивидуальным заданием разработать алгоритмы для заданных функций и функции main(). При разработке функции предусмотреть передачу и возврат значений различных типов.
3 Разработать программу с использованием функций.
4 Выполнить определение функции до функции main() и после нее.
5 Набрать программу на компьютере и устранить ошибки.
6 Получить результат и сделать выводы по работе.
7 Оформить отчет.
8 Подготовиться к защите лабораторной работы, изучив контрольные вопросы по теме.
Индивидуальное задание к лабораторной работе №7
Составить программу реализующую вызов функций H, a, b, c согласно индивидуальному заданию приведенному в таблице 7.1.
Таблица 7.1 - Индивидуальное задание