Почему функции с переменным числом аргументов требуют как минимум двух аргументов? - PullRequest
6 голосов
/ 02 октября 2011

Я пытаюсь закрыть дыру в моих знаниях. Почему функции с переменным числом аргументов требуют как минимум двух аргументов? В основном из main функции C, имеющей argc в качестве количества аргументов, а затем argv как массив массивов символов? Также у Какао Objective-C есть NSString методы, которые требуют форматирования в качестве первого аргумента, а затем массив аргументов ([NSString stringWithFormat:@"%@", foo]). Почему невозможно создать переменную функцию, принимающую только список аргументов?

Ответы [ 5 ]

8 голосов
/ 02 октября 2011

аргументы argc / argv на самом деле не являются переменными.

Функции Variadic (например, printf()) используют аргументы, помещенные в стек, и не требуют как минимум 2 аргумента, но 1.

У вас есть void foo(char const * fmt, ...), и обычно fmt дает подсказку о количестве аргументов.Это минимум 1 аргумент (fmt).

3 голосов
/ 02 октября 2011

C имеет очень ограниченные способности к отражению, поэтому у вас должен быть какой-то способ указать, что именно содержат переменные аргументы - либо указав количество аргументов, либо тип их (или оба), и в этом заключается логика больше параметра. Это требуется стандартом ISO C, поэтому вы не можете его опустить. Если вы чувствуете, что вам не нужны никакие дополнительные параметры, потому что число и тип аргументов всегда постоянны, то в первую очередь нет необходимости в переменных аргументах.

Конечно, вы можете разработать другие способы кодирования числовой / типовой информации в переменных аргументах, таких как значение Sentinel . Если вы хотите сделать это, вы можете просто указать фиктивное значение для первого аргумента и не использовать его в теле метода.

И чтобы быть педантичным к вашему названию, для функций с переменными параметрами требуется только один аргумент (не два). Совершенно верно сделать вызов функции с переменным числом аргументов без дополнительных аргументов:

printf("Hello world");
1 голос
/ 02 октября 2011

Думаю, причина в следующем: в макросе va_start(list, param); вы указываете последний фиксированный аргумент - он необходим для определения адреса начала списка аргументов переменной в стеке.

0 голосов
/ 02 октября 2011

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

Ваши два примера не являются переменными функциями. Они являются функциями с двумя аргументами, но они также выделяют аналогичную проблему. Как узнать размер массива C без дополнительной информации? Вы можете либо передать размер массива, либо описать схему с некоторым значением часового, обозначающим конец массива (т. Е. '\ 0' для строки C).

Как в случае с переменным числом, так и в случае с массивом у вас одна и та же проблема. Как узнать, к какому количеству данных вы имеете законный доступ? Если вы не знаете этого в случае с массивом, вы выйдете за пределы. Если вы не знаете этого в случае с переменным числом, вы будете вызывать va_arg слишком много раз или с неправильным типом.

Чтобы перевернуть вопрос, как бы вы могли реализовать функцию, принимающую переменное число аргументов без передачи дополнительной информации?

0 голосов
/ 02 октября 2011

Как вы узнали бы, предоставил ли пользователь какие-либо аргументы?

Должна быть некоторая информация, чтобы указать это, и C в целом не был предназначен для манипулирования данными за спиной. Так что все, что вам нужно, это заставляет вас пройти явно.

...