Определение подпрограмм

Определение функции состоит из заголовка и тела. Определение функции записывается в следующем виде:

[спецификатор класса памяти] [спецификатор типа] имя функции ([список формальных параметров]) //Заголовок функции

{ //тело функции

}

Заголовок функции задает тип возвращаемого значения, имя функции, типы и число формальных параметров.

Тело функции - это составной оператор, содержащий операторы, определяющие действие функции. Тело функции начинается с фигурной скобки '{' и состоит из объявления переменных и исполняемых операторов. Именно эти операторы, входящие в тело функции, и определяют действие функции. Завершается тело функции закрывающей фигурной скобкой '}'.

При использовании спецификатора класса памяти static функция становится невидимой из других файлов программного проекта, то есть информация об этой функции не помещается в объектный файл. Использование спецификатора класса памяти static может быть полезно для того, чтобы имя этой функции могло быть использовано в других файлах программного проекта для реализации совершенно других задач. Если функция, объявленная со спецификатором класса памяти static, ни разу не вызывалась в данном файле, то она вообще не транслируется компилятором и не занимает места в программной памяти микроконтроллера, а программа-компилятор языка программирования С-51 выдает предупреждение об этом. Это свойство может быть полезным при отладке программ и программных модулей.

Использование спецификатора класса памяти extern используется для связывания подпрограмм, находящихся в других модулях (и возможно написанных на других языках программирования) с вызовом подпрограммы из данного программного модуля. В основном использование этого спецификатора класса памяти эквивалентно предварительному объявлению функции, которое будет рассмотрено далее. Если спецификатор класса памяти функции не указан, то подразумевается класс памяти extern, то есть по умолчанию все подпрограммы считаются глобальными и доступными из всех файлов программного проекта.

Спецификатор типа функции задает тип возвращаемого значения и может задавать любой тип. Если спецификатор типа не задан, то по умолчанию предполагается, что функция возвращает значение типа int. Функция не может возвращать массив или функцию, но может возвращать указатель на любой тип, в том числе и на массив и на функцию. Тип возвращаемого значения, задаваемый в определении функции, должен соответствовать типу в объявлении этой функции.

Функция возвращает значение если ее выполнение заканчивается оператором return, содержащим некоторое выражение. Указанное выражение вычисляется, преобразуется, если необходимо, к типу возвращаемого значения и возвращается в точку вызова функции в качестве результата.

В операторе return возвращаемое значение может записываться как в скобках, так и без них. Если функция определена как функция, возвращающая некоторое значение (подпрограмма-функция), а в операторе return при выходе из нее отсутствует выражение, то это может привести к непредсказуемым результатам.

Все переменные, объявленные в теле функции без указания класса памяти, имеют класс памяти auto, т.е. они являются локальными. Так как глубина стека в процессорах семейства MCS-51 ограничена 256 байтами, то при вызове функций аргументам назначаются конкретные адреса во внутренней памяти микроконтроллера и производится их инициализация. Управление передается первому оператору тела функции и начинается выполнение функции, которое продолжается до тех пор, пока не встретится оператор return или последний оператор тела функции. Управление при этом возвращается в точку, следующую за точкой вызова, а локальные переменные становятся недоступными. При выходе из функции значения этих переменных теряются, так как при вызове других функций эти же ячейки памяти распределяются для их локальных переменных.

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

Параметры подпрограмм

Список формальных параметров - это последовательность объявлений формальных параметров, разделенная запятыми. Формальные параметры - это переменные, используемые внутри тела функции и получающие значение при вызове функции путем копирования в них значений соответствующих фактических параметров.

Порядок и типы формальных параметров должны быть одинаковыми в определении функции и во всех ее объявлениях. Поэтому желательно объявление функции поместить в отдельный файл, который затем можно включить в исходные тексты программных модулей при помощи директивы #include. Типы фактических параметров при вызове функции должны быть совместимы с типами соответствующих формальных параметров. Тип формального параметра может быть любым основным типом, структурой, объединением, перечислением, указателем или массивом. Если тип формального параметра не указан, то этому параметру присваивается тип int.

Для формального параметра можно задавать класс памяти register, при этом для величин типа int спецификатор типа можно опустить. Однако все известные мне компиляторы языка программирования С-51 игнорируют этот спецификатор, так как расположение параметров в памяти микроконтроллера оптимизируется с точки зрения использования минимального количества необходимой внутренней памяти.

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

Таблица 5.8

Номер аргумента char, однобайтовый указатель int, двухбайтовый указатель long,float Нетипизированные указатели
R7 R6,R7 R4 - R7 R1 - R3
R5 R4,R5 R4 - R7 R1 - R3
R3 R2,R3   R1 - R3

Поскольку при вызове функции значения фактических параметров копируются в локальные переменные, в теле функции нельзя изменить значения переменных в вызывающей функции.

Наши рекомендации