{float S=a+b+c;
return S;}
Пример. Функция находит большее из двух переменных. Функция имеет формальные параметры и два оператора return.
int max(int x, int y)
{if (x>y)return x;
else return y;}
Пример. Функция выводит значение переменной на экран. Функция имеет один формальный параметр и не имеет оператора return.
void prn1(int x)
{ printf("Заданное число =%d\n", x);}
Пример. Функция выводит строку на экран. Функция не имеет формальных параметров и оператора return.
void prn2()
{ puts("Моя программа");}
Вызов функции (обращение к функции) – это выражение, в котором указывается имя функции и список фактических параметров в круглых скобках. Результатом этого выражения является возвращаемое значение, тип которого соответствует типу функции:
имя_функции(список фактических параметров)
где список_фактических_параметров – это либо пусто, либо void, либо фактические параметры (константы или заранее определенные переменные, переменные с преобразованием типов, выражения).
При обращении к функции формальные параметры заменяются фактическими параметрами в строгом соответствии с типами параметров. Соответствие между формальными и фактическими параметрами устанавливается по их взаимному расположению в списках.
|
|
Например:
int max(int x, int y)
{if (x>y)return x; else return y;}
void main()
{int a=10,res1,res2; float f=55.9;
res1=max(a,20); // res1=20
res2=max(int(f),a+30);} // res2=55
Пример.
int func1(int a, int b) // Определение функции
{return a+b;}
float sqr(float f, float g) // Определение функции
{return f*g;}
void main()
{int am=2,bm=3,res1;
res1=func1(am,bm); // Вызов функции
float em=2.5,gm=3.0,fm=4.2,res2,res3;
res2=sqr(fm,gm); // Вызов функции
res3=sqr(fm+0.5,sqr(em,gm)); // Вызов функции
int res4=(int)sqr(em,float(am)); } // Вызов функции
Если функция определена после функции main() или в другом файле, то до первого обращения к функции она должна быть описана. Описание функции называется прототипом. Это необходимо для проверки компилятором соответствия типов передаваемых в функцию параметров и возвращаемых значений. В прототипе можно не указывать имена формальных параметров. В конце прототипа обязательна точка с запятой. Примеры прототипов:
float sum(float a, float b, float c);
int max(int, int y);
float sqr(float, float g);
Пример. Функция определена ниже своего первого вызова, перед вызовом помещен прототип.
#include <stdio.h>
int sum(int, int);// Прототип функции – описание функции
void main()
{int a, b=3, g=4;
a=sum(b, g); // Вызов функции
printf("Сумма=%d\n", a); }
int sum(int arg1, int arg2) // Определение функции
{return arg1+arg2;}
2.2 Передача параметров в функции по значению и по указателю
В языке С++ передача параметров (кроме указателей и массивов) в функции при их вызове осуществляется по значению. Это означает, что для передаваемых (фактических) параметров в функции создаются копии этих параметров. Для формальных параметров выделяется память, в которую заносятся значения фактических параметров. Действия, производимые с этими параметрами (копиями) в функции не влияют на переменные вне функции, т.е. на фактические переменные. Формальные параметры недоступны вне тела функции. При выходе из функции выделенная для них память освобождается.
|
|
Пример.
#include <stdio.h>
void func(int intg,float fltp)
{printf("intg=%d &intg=%p ",intg, &intg);
printf("fltp=%f &fltp=%p\n",fltp, &fltp);
intg+=10; fltp*=2;
printf("intg_n=%d fltp_n=%f\n",intg,fltp);}
void main()
{int i=200; float f=100.25;
func(i,f);
printf("i=%d &i=%p f=%f &f=%p\n",i,&i,f,&f);}
В результате работы программы на экран выведется:
intg=200 &intg=8FD8:0FF2 fltp=100.25 &fltp=8FD8:0FF4
intg_n=210 fltp_n=200.5
i=200 &i=8FD8:0FFC f=100.25 &f=8FD8:0FF8
При передаче в функцию указателей (адресов фактических параметров) в функции создаются копии этих адресов, и в теле функции становится известно, где располагаются фактические параметры, и, следовательно, их значения можно изменить.
Пример. В функцию передаются указатели на переменные и значения этих переменных меняются местами:
#include <stdio.h>
void swap(int *a, int *b) // Определение функции
{printf("&a=%p a=%p *a=%d\n",&a,a,*a);
printf("&b=%p b=%p *b=%d\n",&b,b,*b);
int tmp=*a; *a=*b; *b=tmp;
printf("*a_n=%d *b_n=%d\n",*a,*b);}
void main()
{int i=5,j=60;
printf("&i=%p i=%d &j=%p j=%d\n",&i,i,&j,j);
swap(&i,&j); // Вызов функции
printf("i=%d j=%d\n",i,j);}
В результате работы программы на экран выведется:
&i=8FD8:0FFE i=5 &j=8FD8:0FFC j=60
&a=8FD8:0FF4 a=8FD8:0FFE *a=5
&b=8FD8:0FF8 b=8FD8:0FFC *b=60
*a_n=60 *b_n=5
i=60 j=5
2.3 Функции и массивы
При передачемассива в функцию в качестве параметра указывается имя массива. Поскольку имя массива – это указатель-константа, то в функцию передается адрес начала массива и все действия внутри функции производятся именно с элементами массива оригинала. При этом список формальных параметров в заголовке функции имеет две равноправные формы: (покажчик-константа
int func1(int arr[]) {...}
или int func2(int *mass) {...}
В обоих случаях в функции создается копия указателя соответствующего типа, который действует внутри функции как обычный указатель-переменная и может изменять свое значение. Например, arr++. Доступ к элементам массива внутри функции может осуществляться как с помощью индексов (arr[1], arr[i]), так и применяя операцию разыменования указателя (*(arr+1), *(arr+i)).
Для работы со всеми элементами массива необходимо знать количество элементов в массиве. При этом в самой функции узнать размер массива невозможно, т.к. в функцию передается указатель на первый элемент массива и размер этого указателя равен 4 байта.
Есть два способа определения конца массива: 1) в качестве одного из параметров в функцию передается размер массива; 2) последний элемент массива задается каким-либо уникальным значением, которое анализируют в функции.
Пример. Функция вычисляет сумму элементов массива, в качестве одного из параметров в функцию передается размер массива.
#include <stdio.h>
int sum(int N,int x[]) // Определение функции
{int S=0;
for(int i=0;i<N;i++) S+=x[i];
return S;}
void main()
{int a[5]={1,3,5,10,2},c[3]={2,1,6},res1,res2;
res1=sum(5,a); // Вызов функции
printf("сумма элементов массива a=%d\n",res1); // 21
res2=sum(3,c); // Вызов функции
printf("сумма элементов массива c=%d\n",res2);} // 9
Пример. Функция вычисляет количество символов в слове, в качестве признака конца массива используется '\0'.
#include <stdio.h>
int len(char *); // Прототип функции
void main()
{char *name="TERMINATOR";
printf("Длина 1-ой строки=%d",len(name)); // 10
char *str="Высшая математика";
printf("Длина 2-ой строки=%d",len(str)); } // 17
int len(char *c) // Определение функции
{int i=0;
while(c[i++]);
return i-1; } // длина строки без учета символа ' \0 '
Пример. Функция изменяет значения элементов массива, поменяв их на квадраты этих значений, тип функции void
#include <stdio.h>
void exch(int, int []); // Прототип функции
void main()
{int a[5]={1,3,5,8,2};
printf("Массив до изменения: ");
|
|
for(int i=0;i<5;i++) printf(" %d",a[i]);
exch(5,a); // Вызов функции
printf("\nМассив после изменения: ");
for(int i=0;i<5;i++) printf(" %d",a[i]);
}
void exch(int N,int x[]) // Определение функции
{for(int i=0;i<N;i++) x[i]*=x[i];}
В результате на экран выведется:
Массив до изменения: 1 3 5 8 2.
Массив после изменения: 1 9 25 64 4.
2.4 Функции с умалчиваемыми значениями параметров
Функции с умалчиваемыми значениями параметров – это функции, которые имеют спецификацию формальных параметров со значениями по умолчанию. При вызове такой функции умалчиваемый параметр может быть опущен. Спецификация формальных параметров функций значениями по умолчанию имеет вид:
тип имя_параметра=умалчиваемое_значение
В функциях с умалчиваемыми значениями параметров действует правило: если параметр имеет умалчиваемое значение, то все параметры справа от него должны быть так же с умалчиваемыми значениями.
Пример. Функция находит произведение 2-х переменных
#include <stdio.h>
int def(int a=10, int b=3){return a*b;}
void main()
{int am=2, bm=5, res1,res2,res3;
res1=def(); // 10*3=30
res2=def(am); // 2*3=6
res3=def(am,bm); // 2*5=10
printf("res1=%d res2=%d res3=%d\n",res1,res2,res3); }
В результате работы программы на экран выведется:
res1=30 res2=6 res3=10
Если функция с умалчиваемыми параметрами определена после функции main(), то значения умалчиваемых параметров указываются обязательно в прототипе этой функции, а в определении функции (в списке формальных параметров) эти значения не указываются.
Пример. Функция находит сумму 3-х переменных
#include <stdio.h>
int sum(int,int=5,int=10); // Прототип функции
void main()
{int am=20, bm=50, cm=100, s1,s2,s3,s4;
s1=sum(am); // 20+5+10=35
s2=sum(am,bm); // 20+50+10=80
s3=sum(am,bm,cm); // 20+50+100=170
printf("s1=%d s2=%d s3=%d\n",s1,s2,s3);}
int sum(int a,int b,int c) // Определение функции
{return a+b+c;}
В результате работы программы на экран выведется:
s1=35 s2=80 s3=170
2.5 Функции с переменным числом параметров
Функции с переменным числом параметров – это функции, в которых количество и типы параметров определяются только во время их вызова. Синтаксис определения прототипа таких функций:
тип имя(спецификация явных параметров,...);
Последняя запятая необязательна. Многоточие сообщает компилятору, что не нужно проводить дальнейший контроль соответствия количества параметров и их типов при обработке вызова. Переход в списке от параметра к параметру осуществляется с помощью указателя, тип которого является типом переменной. При увеличении указателя на единицу осуществляется переход к следующей переменной такого же типа. В ВС31 функции с переменным числом параметров не работают с типами char, unsigned char, float.
|
|
В таких функциях существуют два способа определения количества параметров: 1) передача в функцию в списке фактических параметров информации об их количестве; 2) добавление параметра–индикатора в конец списка фактических параметров.
Пример. В функцию передается в списке явных параметров количество элементов, которые суммируются.
#include <stdio.h>
int sumi(int i,...)// Определение функции
{int *num=&i; // 1-й параметр – число переменных в списке
int sum=0;
for(;i;i--) sum+=*(++num);// вычисляем сумму со 2-го элемента
return sum;}
double sumd(int i,double d...)// Определение функции
{double *ptr=&d; // указатель на 2-й параметр типа double
double sum=0.0;
for(;i;i--) // 1-й параметр – число переменных в списке
sum+=*(ptr++);
return sum;}
void main()
{int a1=10,a2=20,a3=30,s1,s2;
s1=sumi(3,a1,a2,a3); // сумма 3-х чисел a1,a2,a3
s2=sumi(6,1,a1,3,a2,a3,4); // сумма 6-и чисел
double d1=5.7, d2=1.3,s3;
s3=sumd(4,d1,1.25,d2,2.5); // сумма 4-х чисел
printf("s1=%d s2=%d s3=%.2lf\n",s1,s2,s3);}
В результате работы программы на экран выведется:
s1=60 s2=68 s3=10.75
Пример. В функции вычисляется произведение элементов, при этом каждый элемент сравнивается с параметром–индикатором, который находится в конце списка явных параметров.
#include <stdio.h>
#define term 0.0
double mult(double arg...) // Определение функции
{double a=1.0, *ptr=&arg;
if(*ptr==0.0) return 0.0;
for(;*ptr!=term;ptr++)
a*=*ptr;
return a;}
void main()
{double a=2.5,b=2.0,md1,md2;
md1=mult(a,b,0.3,term);
md2=mult(0.5,a,4.0,b,1.1,term);
printf("md1=%.2lf md2=%.2lf\n",md1,md2);}
В результате работы программы на экран выведется:
md1=1.50 md2=11.00
При работе с функциями, имеющими переменное параметров, имеется набор макроопределений, помещенных в заголовочном файле stdarg.h:
Макрокоманда void va_start (va_list param, последний явный параметр) связываетвспомогательный параметр param с последним явным параметром в списке.
Макрокоманда type va_arg (va_list param,type) перемещает указатель param на число байтзаданного типа type.
Макрокоманда va_end (va_list param) вызывается после обработки списка и организует корректный возврат из функции (вместо оператора return).
2.6 Передача параметров в функцию main()
В функцию main(), как и в любую другую функцию, могут передаваться параметры. Для передачи параметров в функцию main() ее следует описать в таких формах:
[тип] main(int argc, char **argv){...}
[тип] main(int argc, char **argv, char **envp){...}
[тип] – тип функции main может быть void или int.
Параметр int argc определяет число слов в командной строке.
Параметр char **argv ‑ указатель на массив строк, вводимых из командной строки. Массив строк –это массив указателей, являющихся адресами первых символов этих строк. Размер этого массива строк равен argc. Нулевое слово, на которое указывает указатель argv[0], всегда является спецификацией запускаемой на выполнение программы (именем программы с расширением .exe).
Параметр char **envp ‑ это указатель на массив указателей на строки среды программы. С помощью этого параметра в программу можно передать всю информацию среде окружения программы, которая определяет некоторые особенности операционной системы и др.
В следующих примерах демонстрируется передача параметров в функцию main. Для работы программ их необходимо запустить из командной строки, например в среде FAR, NC, VC, DN и др.
Пример.
#include <stdio.h>
#include <conio.h>
int main(int argc,char**argv,char**envp)
{clrscr();
for(int i=0;i<argc;i++)
printf("argv[%d]=%s\n",i,argv[i]);
getch();
puts("Среда окружения");
while(*envp) puts(*envp++);
getch();
return 0;}
Пусть исполняемый файл этой программы prog1.exe расположен в корневом каталоге диска C:\. Тогда, если в командной строке набрать c:\>prog1.exe my age 19, то результат работы программы может быть такой:
argv[0]=C:\PROG1.EXE
argv[1]=my
argv[2]=age
argv[3]=19