Не существует прямого способа для функции, которая использует va_arg
для определения количества или типа(ов) аргументов, переданных данным вызовом.
Предлагаемый вами метод, в частности:
while(va_arg(argPtr, char) != NULL)
это неверно. va_arg(argPtr, char)
дает значение типа char
, а NULL
является константой нулевого указателя. (NULL
обычно определяется как 0
, что эквивалентно нулевому символу '\0'
, но на это нельзя полагаться.)
Любая функция с переменным числом аргументов должна иметь возможность для вызывающей стороны указать количество и типы аргументов. Например, функции *printf
делают это через (невариативную) строку формата. Функции POSIX execl*()
ожидают последовательность из char*
аргументов; конец списка аргументов помечен вызывающим кодом (char*)NULL
. Возможны и другие методы, но почти все они зависят от информации, предоставляемой во время выполнения в аргументах. (Вы можете использовать другой метод, например, глобальную переменную. Пожалуйста, не делайте этого.)
Это возлагает на вызывающего бремя обеспечения согласованности аргументов, передаваемых функции. Сама функция не имеет возможности подтвердить это. Неправильные вызовы, такие как printf("%d\n", "hello")
или execlp("name", "arg1")
, имеют неопределенное поведение.
Еще одно: вы не можете использовать va_arg
с аргументом типа char
. Когда вы вызываете функцию с переменным числом аргументов, аргументы, соответствующие , ...
, расширяются. Целочисленные аргументы типов более узких, чем int
, повышаются до int
или unsigned int
, а аргументы типа float
повышаются до double
. Если вызывающий объект передает аргумент типа char
, функция должна вызывать va_arg(argPtr, int)
.
(В очень неясных обстоятельствах, с которыми вы вряд ли столкнетесь, char
можно повысить до unsigned int
. Это может произойти только в том случае, если простое char
не имеет знака и sizeof (int) == 1
, что подразумевает, что байт состоит как минимум из 16 бит.)
person
Keith Thompson
schedule
20.05.2016
n
является строкой формата, то обычно вы ведете себя какprintf
и семья, сопоставляя количество спецификаторов формата с количеством параметров. Вы уверены, что передается просто переменное количествоchar
? Если это так, вы можете сопоставить-1
или0
или что-то еще, но NULL - плохая идея по причинам, изложенным @hvd в его комментариях ниже. - person Ryan Haining   schedule 21.05.2016char
, вам следует использоватьsigned char
, если вы имеете дело только со значениями в диапазоне [0, 128) (ascii), тогда -1 должно быть хорошо. - person Ryan Haining   schedule 21.05.2016char
аргументов, почему бы просто не передать строку? (Есть некоторые случаи, когда это не сработает, но это очевидное решение.) - person Keith Thompson   schedule 21.05.2016int
, вам нужно выбрать какое-то специальное значениеint
, например 0 или -1. Если вы передаете строки, т. е.char *
, вам нужно завершить их с помощью(char *) NULL
, как, например, требуетexecl()
. - person Tom Karzes   schedule 21.05.2016