Программа в Си, связь между функциями и передача параметров в функцию

Программы на языке Си обычно состоят из некоторого числа отдель­ных функций (подпрограмм), среди которых должна быть одна с именем main. С этой функции начинается выполнение программы. Как правило, функции имеют небольшие размеры, и могут находиться как в одном, так и в нескольких файлах. Если функции располагаются в различных физических файлах, то для выполнения их как единой программы, необходимо собрать их в файле проекта. В языке Си запрещено определять одну функцию внутри другой, поэтому все имена функций являются глобальными. Связь между функциями осуществляется через аргументы, возвращаемые значения и внешние (глобальные) переменные. Передача зна­чения (возврат значения) из вызванной функции в вызвавшую реализуется с помощью опера­тора возврата, который записывается в следующем формальном виде:

return выражение;

Таких операторов в подпрограмме может быть несколько, и тогда они фиксируют соответствующие точки выхода. Вызвавшая функция мо­жет при необходимости игнорировать возвращаемое значение. После слова return можно ничего не записывать. В этом случае вызвавшей функции никакого значения не передается. Управление передается вызвавшей функции и в случае выхода "по концу" без использования return (последняя закрыва­ющаяся фигурная скобка ). Примеры:

#include <stdio.h>

int f1 (void) {printf("rabotaet f1()"); return 1;} //функция возвращает значение 1

void main (void) {int k=f1();}// возвращаемое значение используется

//во внешней программе

 

#include <stdio.h>

int f1 (int a,int b) {return a+b;} //функция принимает параметры и возвращает значение

Void main (void)

{int a=17; int b=16;printf("%d",f1(a,b));} //возвращаемое значение распечатывается в main

 

#include <stdio.h>

f1 (int a,int b) {a+b;}//функция принимает параметры

// и возвращает значение по умолчанию

void main (void) //результат работы тот же, что и в предыдущем случае

{int a=17; int b=16;printf("%d",f1(a,b));} //хотя программа некорректна, о чем выдается

//предупреждение, как и в варианте строки: {int a=17,b=16, с=f1(a,b); printf("%d",c);

 

Пример использования глобальных переменных:

#include <stdio.h>

#include <conio.h>

int a,b; //глобальные переменные

int f1 (int x) //х – локальный формальный параметр, принимает значение

{return (a+b)*x;} //фактического параметра k при вызове функции f1(k);

Void main (void)

{clrscr();int k=35; a=10;b=12; int c= f1(k); printf("%d",c); }//с и k– локальные в main

 

Если некоторые переменные, константы, массивы, структуры объявлены как глобальные, то их не надо включать в описок параметров вызванной функции. Она все равно получит к ним доступ.

Программе main также могут быть переданы параметры при запуске. В этом случае текст программы может выглядеть следующим образом:

#include <stdio.h>

void main(int argc, char *argv[])

//здесь в argc – количество элементов в строке запуска программы;

{char *s; s=argv[0]; // argv[] – массив ссылок на элементы этой строки

printf("name programm=\"%s\"\n",s); //первый элемент строки запуска

if(argc > 1) //конструкция \” используется для ввода в текст символа кавычки «“»

{s=argv[1]; printf("parametr programm=\"%s\"\n",s);}//второй элемент строки запуска

}

Если создать загрузочный модуль такой программы, например с именем f1.exe, в каталоге D:\BORLANDC\MY_WORK и запустить его из этого каталога командой, например: f1 77, то в результате получим вывод на экран двух строк:

name programm=” D:\BORLANDC\MY_WORK \F1.EXE”

parametr programm=”77”

В языке С аргументы функции передаются по значению, т.е. вызванная функция получает в именах формальных параметров временную копию каждого аргумента, а не его адрес. Это означает, что в самой функции не может изменяться значение самого оригинального аргумента в вызвавшей ее программе. Ниже будет показа­но, как убрать это ограничение. Если же в качестве аргумента функ­ции используется имя массива, то передается начало массива (адрес начала массива), а сами элементы не копируются. Функция может изменять элементы массива, сдвигаясь (индексированием) от его начала. Рассмотрим, как соответствуют друг другу параметры в вызове и в списке функции. Пусть в вызывающей программе вызов функции реализован следующим образом:

int a,b=73, c=40; а = fun(b,с);

Здесь b и о - аргументы, значения которых передаются в вызываемую подпрограмму. Если описание вызываемой функции начинается так:

void fun(int b,int c);

то имена передаваемых аргументов в вызове и в программе fun будут одинаковыми. Если же описание функции начинается, например, строкой void fun(int i,int j); , то вместо имени b в вызвавшей функции для того же аргумента в функ­ции fun будет использовано имя i, а вместо с – j .

Пусть обращение к функции имеет вид

а = fun(&b,&c);

Здесь подпрограмме передаются адреса переменных b и о. Поэтому про­тотип (заголовок вызываемой функции) должен быть, например, таким:

void fun(int *k,int *c);

Теперь k получает адрес передаваемой переменной b, а с - адрес пе­редаваемой переменной с. В результате в вызвавшей программе с - это переменная целого типа, а в вызванной программе с - это указатель на переменную целого типа. Если в вызове записаны те же имена, что и в списке параметров, но они записаны в другом порядке, то все равно устанавливается соответствие между i-м именем в списке и i-м именем в вызове.

Выше уже указывалось, что переменные передаются функции по значению, поэтому нет прямого способа в вызванной функции изменить некоторую переменную в вызвавшей функции. Однако это легко сделать, если передавать в функцию не переменные, а их адреса. Пример:

#include <stdio.h>

void f1 (int * a,int b, int * c1)//принимаемые аргументы: a – по адресу, b – по значению,

{*c1=*a+b; return;} //c1- по адресу. Теперь указатель с1 ссылается на с

void main (void) // и значения с=*с1;

{int c, a=17, b=16; f1(&a,b,&c);//передаваемые параметры: a – по адресу; b – по значентию

printf("%d",c); } // с – по адресу. Результат вычисления получаем в с.

Рассмотрим теперь, как функции можно передать массив в виде па­раметра. Здесь возможны три варианта. Причем в прототипе и теле записи могут комбинироваться из этих вариантов.

int mn[100] – объявлен массив. В функцию передается (прототип)

int mn []

int *mn

1. Параметр задается как массив (например: int [100]).

2. Параметр задается как массив без указания его размерности (например: int m[ ]).

3. Параметр задается как указатель (например: int *m, прототип int f1(int *mn).

Независимо от выбранного варианта вызванной функции указатель передается на начало массива. Сами же элементы массива не копируются.

#include <stdio.h>

void f1 (int x[20],int k)

{int i; for (i=0; i<k; i++) x[i]=i;}

#define k 5

Void main (void)

{ int a[k],i; f1(a,k);

for (i=0; i<k; i++) printf("%d;",a[i]); }

Вызываемая функция может быть записана и в виде

void f1 (int x[],int k) {int i; for (i=0; i<k; i++) x[i]=i;} //или

void f1 (int * x,int k) {int i; for (i=0; i<k; i++) x[i]=i;}

Функции в языке С необходимо объявлять. Мы будем использовать уже рассмотренные ранее конструкции, называемые прототипом. В соот­ветствующем объявлении будет дана информация о параметрах. Она представляется в следующем виде: тип функция (параметр_1,параметр_2,...,параметр_n);

Для каждого параметра можно указать только его тип (например, тип функции (int, float);), а можно дать и его имя (например, тип функция (int a,float b);). В языке C разрешается создавать функции с переменным числом параметров. Тогда при задании прототипа вместо последнего из них указывается многоточие (например void f1(int a, float b,…).

Можно определить и функцию void f1 (...) {тело функции}и обращение f1 (a1, a2), где а1 и а2 достаются каким-либо особым образом из стека или известны как глобальные).

 








Дата добавления: 2016-04-14; просмотров: 2626;


Поиск по сайту:

При помощи поиска вы сможете найти нужную вам информацию.

Поделитесь с друзьями:

Если вам перенёс пользу информационный материал, или помог в учебе – поделитесь этим сайтом с друзьями и знакомыми.
helpiks.org - Хелпикс.Орг - 2014-2024 год. Материал сайта представляется для ознакомительного и учебного использования. | Поддержка
Генерация страницы за: 0.01 сек.