Функции со списками аргументов переменных (C++)
Функции, в объявлениях которых в качестве последнего члена указано многоточие (...), могут принимать переменное число аргументов. В таких случаях C++ обеспечивает проверку типа только для явно объявленных аргументов. Переменные списки аргументов можно использовать, если функция должна быть настолько универсальной, что могут изменяться даже количество и типы аргументов. Семейство функций — это пример функций, использующих списки аргументов переменной.printf
argument-declaration-list
Функции с переменными аргументами
Чтобы получить доступ к аргументам после объявления, используйте макросы, содержащиеся в стандартном файле <stdarg.h> , как описано ниже.
Блок, относящийся только к системам Майкрософт
Microsoft C++ допускает указывать многоточие в качестве аргумента, если это последний аргумент и перед многоточием стоит запятая. Поэтому объявление int Func( int i, ... );
допускается, а объявление int Func( int i ... );
— нет.
Завершение блока, относящегося только к системам Майкрософт
В объявлении функции, которая принимает переменное число аргументов, требуется по крайней мере один аргумент-местозаполнитель, даже если он не используется. Если этот аргумент-местозаполнитель не указан, доступ к остальным аргументам невозможен.
Когда аргументы типа char
передаются в качестве аргументов переменной, они преобразуются в тип int
. Аналогичным образом, когда аргументы типа float
передаются в качестве аргументов переменной, они преобразуются в тип double
. Для аргументов остальных типов могут выполняться обычные восходящие приведения целочисленных типов и типов с плавающей запятой. Дополнительные сведения см. в разделе "Стандартные преобразования".
Функции, которым необходимы списки с переменным количеством аргументов, объявляются с многоточием (...) в списках аргументов. Используйте типы и макросы, описанные в <файле stdarg.h> , чтобы получить доступ к аргументам, передаваемым списком переменных. Дополнительные сведения об этих макросах см. в va_arg , va_copy, va_end va_start. в документации по библиотеке времени выполнения C.
В следующем примере показано, как макросы работают вместе с типом (объявленным в <stdarg.h>):
// variable_argument_lists.cpp
#include <stdio.h>
#include <stdarg.h>
// Declaration, but not definition, of ShowVar.
void ShowVar( char *szTypes, ... );
int main() {
ShowVar( "fcsi", 32.4f, 'a', "Test string", 4 );
}
// ShowVar takes a format string of the form
// "ifcs", where each character specifies the
// type of the argument in that position.
//
// i = int
// f = float
// c = char
// s = string (char *)
//
// Following the format specification is a variable
// list of arguments. Each argument corresponds to
// a format character in the format string to which
// the szTypes parameter points
void ShowVar( char *szTypes, ... ) {
va_list vl;
int i;
// szTypes is the last argument specified; you must access
// all others using the variable-argument macros.
va_start( vl, szTypes );
// Step through the list.
for( i = 0; szTypes[i] != '\0'; ++i ) {
union Printable_t {
int i;
float f;
char c;
char *s;
} Printable;
switch( szTypes[i] ) { // Type to expect.
case 'i':
Printable.i = va_arg( vl, int );
printf_s( "%i\n", Printable.i );
break;
case 'f':
Printable.f = va_arg( vl, double );
printf_s( "%f\n", Printable.f );
break;
case 'c':
Printable.c = va_arg( vl, char );
printf_s( "%c\n", Printable.c );
break;
case 's':
Printable.s = va_arg( vl, char * );
printf_s( "%s\n", Printable.s );
break;
default:
break;
}
}
va_end( vl );
}
//Output:
// 32.400002
// a
// Test string
Приведенный выше пример иллюстрирует следующие важные правила:
Перед тем как обращаться к аргументам из списка переменной длины, необходимо установить его маркер в качестве переменной типа
va_list
. В приведенном выше примере этот маркер имеет имяvl
.К отдельным аргументам можно обращаться при помощи макроса
va_arg
. Макросуva_arg
необходимо указать тип получаемых аргументов, чтобы он мог перенести из стека нужное количество байтов. Если вы ошибетесь и укажете другой тип, а его размер не будет совпадать с типом, который вызывающая программа передает макросуva_arg
, это может привести к непредсказуемым результатам.Результат, полученный при помощи макроса
va_arg
, необходимо явным образом преобразовывать в нужный вам тип.
Для завершения обработки списка с переменным количеством аргументов необходимо вызвать макрос.va_end
Обратная связь
https://aka.ms/ContentUserFeedback.
Ожидается в ближайшее время: в течение 2024 года мы постепенно откажемся от GitHub Issues как механизма обратной связи для контента и заменим его новой системой обратной связи. Дополнительные сведения см. в разделеОтправить и просмотреть отзыв по