Функции на языке С. Описание, передача параметров, вызов функции.
Описание функции:
Тип имя (список формальных параметров)
{
тело функции
}
Где
тип – тип результата
имя – имя функции
список формальных параметров – содержит как имена параметров, так и их спецификации
тело функции:
определения переменных
исполняемые операторы
примеры:
//функция возвращает значение целого типа
int max(int x, int y)
{ if (x>y) return x; else return y;}
//функция не возвращает значения
void print(float x)
{
printf (“\n значение аргумента равно %7.2f \n”, x);
}
Прототип функции:
Прототип функции состоит только из заголовка :
Тип имя (список формальных параметров)
n При описании прототипа функции список формальных параметров может содержать только спецификации параметров
n Прототип должен быть обязательноесли описание функции стоит ниже вызывающей ее функции
Пример: верное обращение к функции
int max(int ,int ); // прототип функции
void main()
{ int a,b,c; float m;
scanf(“%d %d %d”, &a,&b,&c);
m=(float)(max(a,b)+max(b,c))/max(a,a); printf(“\n m=%7.2f”,m);
} // main
//описание функции
int max(int x,int y)
{ (if (x>y) return x; else return(y); }
Даны два комплексных числа
z=a+b*i, y=c+d*I
Вычислить
|x|, |y|, |x+y|
Решение:
float mod(float a, float b);// прототип функции
void main()
{
float a,b,c,d,mx,my,mxy;
scanf(“%f %f %f %f”, &a,&b,&c,&d);
mx=mod(a,b); //вызов функции
my=mod(c,d);
mxy=mod(a+c,b+d);
printf(“\n|x|=%f |y|=%f |x+y|=%f “, mx,my,mxy);
}
// описание функции
float mod (float a, float b);
{
float s=sqrt(a*a+b*b);
return s;
}
Здесь:
a и b – формальные параметры
s – локальная переменная
Вызов функции:
При вызове функции формальные параметры заменяются на фактические
Количество, типы и порядок следования фактических параметров должен полностью соответствовать перечню формальных параметров
Пример:
Пусть задана фунция
int max(int x,int y)
{ (if (x>y) return x; else return(y); }
Вызов max(a,b); и max(b,a); для целых значений a и b даст различные результаты.
Если переменная s – типа float, то вызов функции max(s,a); даст сообщение об ошибке
Передача параметров:
Существует два способа передачи параметров:
n По значению
Операторы функции работают только с копиями передаваемых параметров. Возможности изменить сами значения у функции нет
n По адресу
Функция осуществляет доступ к ячейкам памяти по передаваемым адресам и может изменить значения аргументов
Например:
Пусть необходимо написать функцию, которая меняет два значения x и y местами.
#include <stdio.h>
void swap(int x, int y)
{ printf(“начальные значения:%d %d\n”, x,y);
int temp=y; y=x;x=temp;
printf(“измененные значения: %d %d \n конец функции\n”, x,y);
}//swap
void main()
{
int a,b;
printf(“a=“);scanf(“%d”, &a);
printf(“b=“);scanf(“%d”, &b);
swap(a,b);
printf(“новые значения : ”, a,b);
}// main
Результаты выполнения программы
a=10
b=20
начальные значения: 10 20
измененные значения: 20 10
конец функции
новые значения : 10 20
Выводы: при передаче параметров по значению после выхода из функции параметры имеют первоначальные значения
Функция работает с копиями параметров
Указатели и основные операции с указателями.
Указатели предназначены для хранения адресов памяти
Указатель не является самостоятельным типом: он всегда связан с каким-либо конкретным типом
Существуют указатели трех типов
n Указатель на объект – в этом случае в указателе хранится адрес области памяти, в которой хранятся данные определенного типа
n Указатель на функцию – содержит адрес в сегменте кода, по которому располагается исполняемый код функции
n Указатель на void – применяется в том случае, когда конкретный тип объекта заранее не определен
Указатель может быть
n Константой
n Переменной
n Указывать на константу
n Указывать на переменную
Примеры:
int I; // целая переменная
const int ci=1;// целая константа
int *pi;//указатель на целую переменную
const int *pci; //указатель на целую константу
int * const cp=&i; //указатель-константа на целую переменную
const int * const cpc=&ci;
//указатель-константа на целую константу
Инициализация указателей:
Присваивание указателю адреса существующего объекта:
int a=5; // инициализируем целую переменную
int *pa=&a; // в указатель записывается адрес а
Операции с указателями:
Разадресация (разыменование) –
используется для получения или изменения значения по заданному адресу
Обозначение: *
int x=10, y;//переменные типа int
int *px=&x; //указателю присваиваем значение адреса переменной х
y=*px; //значение y становится равным 10
int x, y;//переменные типа int
int *px=&x; //указателю присваиваем значение адреса переменной х
*px=10; //значение х становится равным 10
Арифметические операции:
n Инкремент – увеличение указателя на величину sizeof(тип)
Декремент -уменьшение указателя на величину sizeof(тип):
int *p;
float *s;
p++;//увеличивает p на 2
s++;// увеличивает s на 4
Разность двух указателей – это разность их значений, деленная на размер типа в байтах
int x=10,*px, y=20,*py;
px=&x; py=&y;
float *a,*b;
printf(“px=%d, py=%d, px-py=%d\n”,
px,py,px-py);
printf(“a=%d, b=%d, a-b=%d\n”,a,b,a-b);
Результат выполнения:
px=3fff4, py=3fff2, px-py=1
a=4ff26, b=4ffe10, a-b=4
Сумма указателя и константы
int *px; cout<<“px=“<<px<<endl;
px=px+4;
cout<<“px+4=“<<px<<endl;
Результат: px=3fff4
px+4=3fffc
Замечания:
n Арифметические операции используются только для указателей одного типа
Сложение указателей не допускается
Передача параметров по адресу:
Пример:
Void swap(int *a, int *b)
{ int temp=*a;
*a=*b;
*b=temp;
}
Вызов функции:
Void main()
{ int a=10,b=2;
printf(“\n a=%d b=%d”,a,b);
swap(&a,&b);
printf(\n new \n a=%d b=%d”,a,b);
}
Результат: A=10 b=2
New
A=2 b=10