double arrow

Макрокоманды обработки списков с переменным числом параметров

Обычные фиксированные аргументы имеют индивидуальные имена, и можно использовать эти имена, чтобы обратиться к их значениям. Но необязательные аргументы не имеют никаких имен кроме "...". Единственный способ обращаться к ним – последовательно, в порядке, в котором они написаны, для чего используются специальные макрокоманды из "stdarg.h" в следующем процессе:

1) Инициализация переменной указателя аргумента типа va_list, используя va_start. Указатель аргумента, после инициализации указывает на первый необязательный аргумент.

2) Обращение к необязательным аргументам последовательными обращениями к va_arg. Первое обращение к va_arg дает первый необязательный аргумент, следующее обращение – второй, и т. д.

3) Вызов va_end для окончания работы.

Шаги 1 и 3 должны выполниться в функции, которая принимает необязательные аргументы. Однако, можно передавать va_list переменную как аргумент другой функции и выполнять весь или часть шага 2 там. Можно выполнять всю последовательность из трех шагов несколько раз внутри одного вызова функции. Имеются описания макрокоманд, используемых, чтобы отыскать переменные аргументы. Эти макрокоманды определены в заглавном файле " stdarg.h ".

va_list (тип данных)

Тип va_list используется для переменной указателя аргумента.

void va_start (va_list ap, last_required) (макрос)

Эта макрокоманда инициализирует переменную указателя аргумента ap, чтобы указать на первый из необязательных аргументов текущей функции; last_required должен быть последний требуемый аргумент функции.

type va_arg (va_list ap, type) (макрос)

Va_arg макрокоманда возвращает значение следующего необязательного аргумента, и изменяет значение ap, чтобы указать на последующий аргумент. Таким образом, последовательные использования va_arg возвращают последовательные необязательные аргументы.

Тип значения, возвращенного va_arg – type как определено в обращении. type должен быть самоподдерживающийся тип (не char или short int или float) который соответствует типу фактического аргумента.

void va_end (va_list ap) (макрос)

Он заканчивает использование ap. После обращения va_end, дальнейшие va_arg обращения с тем же самым ap не могут работать. Следует вызывать va_end перед возвращением из функции, в которой va_start вызывался с тем же самым аргументом ap.

Пример:

#include <stdarg.h>#include <iostream.h>int add_em_up (int count,...){ va_list ap; int i,sum; va_start(ap,count); sum = 0; for(i=0;i<count;i++) sum+=va_arg(ap,int); va_end (ap); return sum;} void main (){ cout<<add_em_up(3,5,5,6); cout<<add_em_up(10,1,2,3,4,5,6,7,8,9,10);}

Резюме

Макросы имеют большое значение в С, но в С++ они используются значительно реже. Практически каждый макрос свидетельствует о недостатке в языке программирования, программе или программисте. Так как макросы изменяют текст программы до обработки его компилятором, они создают проблемы для инструментов отладки. Кроме того, на использованием макросов накладывается ряд ограничений:

- имена макросов нельзя перегружать:

#define PRINT(a,b) cout<<(a)<<(b)#define PRINT(a,b,c) cout<<(a)<<(b)<<(c)

- рекурсивные вызовы создают проблемы, которые препроцессор не может решить

#define FAC(n)(n>1)?n*FAC(n-1):1

Макросы манипулируют строками символов и мало что знают о синтаксисе С++. Компилятор видит текст после макроподстановки, поэтому ошибка в макросе будет замечена после подстановки, что приводит к очень странным сообщениям об ошибках.


Понравилась статья? Добавь ее в закладку (CTRL+D) и не забудь поделиться с друзьями:  



Сейчас читают про: