Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
AllCandC++Lectures.docx
Скачиваний:
2
Добавлен:
25.09.2019
Размер:
52.56 Кб
Скачать

Функции с переменным числом аргументов

В СИ имеются функции, которым можно передавать разное число фактических параметров. Например: функция printf. У нее есть 1 обязательный аргумент, форматная строка. Помимо нее могут присутствовать другие аргументы, но их количество никак не оговаривается. Появление необязательных аргументов приводит к тому, что компилятор теряет возможность осуществлять проверку их типов. В СИ любая функция с переменным числом аргументов должна иметь хотя бы 1 явный аргумент. У функции printf это формат.

Реализация функций с переменным числом аргументов

Основная проблема в том, каким образом обрабатывать те фактические параметры, для которых нет соответствующих формальных. Для работы с переменным списком аргументов, в заголовочном файле stdarg.h определено несколько макросов, имена которых начинаются с va_. Обработка переменного списка состоит из нескольких этапов.

1) определяем переменную, которая будет хранить указатель на переменную части списка. Эта переменная имеет тип va_list, которая является синонимом void*.

2) необходимо инициализировать эту переменную. Для этого вызывается макрос va_start, которому передаются два аргумента. 1й это переменная, для хранения указателя, а 2й это имя последнего фиксированного аргумента функции. Имя последнего фиксированного аргумента позволяет найти адрес первого нефиксированного.

3) с помощью макроса va_arg с двумя аргументами поочередно считываются значения добавочных параметров. Из этого следует, что программист должен заранее знать типы аргументов, которые могут быть помещены в произвольный список. Он вызывается для каждого дополнительного аргумента, но необходимо каким-то образом определить, когда список фактических параметров будет исчерпан. Это задача программиста. Решения могут быть разные. Например: 1й дополнительный аргумент может описывать общее количество дополнительных аргументов. Если дополнительные параметры имеют один и тот же тип, то признаком конца может служить некоторое специальное значение, например 0. А в printf дополнительные параметры отыскиваются для каждой спецификации формата.

4) после того как работа с переменной частью списка закончена, необходимо вызвать макрос va_end.

Особенности вызова функции в си

При вызове функции создается фрейм вызова, в котором в том числе размещаются значения фактических параметров. Есть два подхода: 1) аргументы помещаются в стек в порядке их записи в вызове. Этот метод используется в паскале. Однако для СИ он неудобен. Если число параметров переменное, то найти где находится первый аргумент, становится трудно. Поэтому в СИ используется обратный порядок. Тогда положение первого элемента определяется указателем на вершину стека. Когда число аргументов фиксировано, то вызываемая функция сама может освободить фрейм вызова, когда закончит выполняться. Поэтому компилятор добавляет в функцию необходимый для этого код. Так происходит в паскале. Если число аргументов - переменная, то о размере фрейма вызова знает вызывающая функция. Поэтому она отвечает за освобождение стека. Так происходит в СИ. Некоторые версии компиляторов позволяют управлять соглашениями, которые используются при вызове конкретной функции. Если перед определением функции записать pascal, то будут использоваться соглашения паскаля, но число аргументов должно быть фиксировано. Если явно написано cdecl (c declaratiom), то используются соглашение СИ.

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]