Есть ли способ указать аргументы по умолчанию для функции в C?
c
arguments
default-parameters
Натаниэль Флат
источник
источник
Ответы:
На самом деле, нет. Единственный способ - написать функцию varargs и вручную ввести значения по умолчанию для аргументов, которые вызывающая сторона не передает.
источник
open(2)
Системный вызов использует это для необязательного аргумента , который может присутствовать в зависимости от требуемых параметров, иprintf(3)
считывает строку формата , которая определяет , сколько аргументов там будет. Оба используют varargs довольно безопасно и эффективно, и, хотя вы, конечно, можете их испортить,printf()
особенно это кажется довольно популярным.Вау, все здесь такие пессимисты. Ответ - да.
Это не тривиально: к концу мы получим базовую функцию, вспомогательную структуру, функцию-оболочку и макрос вокруг функции-оболочки. В моей работе у меня есть набор макросов для автоматизации всего этого; как только вы поймете поток, вам будет легко сделать то же самое.
Я написал это в другом месте, поэтому вот подробная внешняя ссылка, чтобы дополнить резюме здесь: http://modelingwithdata.org/arch/00000022.htm
Мы хотели бы включить
в функцию, которая принимает значения по умолчанию (я = 8, х = 3,14). Определите сопутствующую структуру:
Переименуйте вашу функцию
f_base
и определите функцию-оболочку, которая устанавливает значения по умолчанию и вызывает базу:Теперь добавьте макрос, используя переменные макросы Си. Таким образом, пользователям не нужно знать, что они на самом деле
f_args
заполняют структуру, и думать, что они делают обычное:Хорошо, теперь все следующее будет работать:
Проверьте правила того, как составные инициализаторы устанавливают значения по умолчанию для точных правил.
Одна вещь, которая не будет работать:
f(0)
потому что мы не можем различить отсутствующее значение и ноль. По моему опыту, это то, что нужно остерегаться, но о нем можно позаботиться, когда возникнет такая необходимость - половина времени, по умолчанию, ваше значение по умолчанию равно нулю.Я столкнулся с трудностями при написании этого, потому что я думаю, что именованные аргументы и значения по умолчанию действительно делают кодирование на C проще и еще веселее. И Си потрясающе, потому что он такой простой и все еще имеет достаточно, чтобы сделать все это возможным.
источник
{}
(пустой инициализатор) является ошибкой C99.#define vrange(...) CALL(range,(param){.from=1, .to=100, .step=1, __VA_ARGS__})
Да. :-) Но не так, как вы ожидаете.
К сожалению, C не позволяет вам перегружать методы, поэтому вы получите две разные функции. Тем не менее, вызывая f2, вы на самом деле вызываете f1 со значением по умолчанию. Это решение «Не повторяй себя», которое поможет вам избежать копирования / вставки существующего кода.
источник
Мы можем создавать функции, которые используют именованные параметры (только) для значений по умолчанию. Это продолжение ответа БК.
Стандарт C99 определяет, что более поздние имена в инициализации переопределяют предыдущие элементы. У нас также могут быть некоторые стандартные позиционные параметры, просто измените макрос и сигнатуру функции соответственно. Параметры по умолчанию могут использоваться только в стиле именованных параметров.
Выход программы:
источник
OpenCV использует что-то вроде:
Если пользователь не знает, что ему следует написать, этот трюк может быть полезен:
источник
Нет.
Даже самый последний стандарт C99 не поддерживает это.
источник
Нет, это особенность языка C ++.
источник
Краткий ответ: Нет.
Немного более длинный ответ: есть старый, старый обходной путь, когда вы передаете строку, которую вы анализируете для необязательных аргументов:
где opt может включать в себя пару «имя = значение» или что-то, что вы бы назвали как
Очевидно, что это только иногда полезно. Обычно, когда вам нужен единый интерфейс для семейства функциональных возможностей.
Вы все еще найдете этот подход в кодах физики элементарных частиц, которые написаны профессиональными программами на c ++ (например, ROOT ). Его главное преимущество заключается в том, что он может быть расширен практически до бесконечности при сохранении обратной совместимости.
источник
struct
, чтобы вызывающий сделал его, заполнил поля для разных опций, а затем передал его по адресу или передалNULL
опции по умолчанию.Вероятно, лучший способ сделать это (что может или не может быть возможным в вашем случае в зависимости от вашей ситуации) - это перейти на C ++ и использовать его как «лучший C». Вы можете использовать C ++ без использования классов, шаблонов, перегрузки операторов или других расширенных функций.
Это даст вам вариант C с перегрузкой функций и параметрами по умолчанию (и любыми другими функциями, которые вы выбрали). Вы просто должны быть немного дисциплинированными, если вы действительно серьезно относитесь к использованию только ограниченного подмножества C ++.
Многие люди скажут, что это ужасная идея - использовать C ++ таким образом, и у них может быть смысл. Но это просто мнение; Я думаю, что вполне допустимо использовать функции C ++, которые вам удобны, без необходимости покупать все это целиком. Я думаю, что значительная часть причины успеха C ++ заключается в том, что в первые годы он использовался огромным количеством программистов именно таким образом.
источник
Еще один вариант использует
struct
s:источник
Нет.
источник
20202020
в шестнадцатеричном формате, но как мне его напечатать?Еще один трюк с использованием макросов:
Если передается только один аргумент,
b
получает значение по умолчанию (в данном случае 15)источник
Нет, но вы можете рассмотреть возможность использования набора функций (или макросов) для аппроксимации с использованием аргументов по умолчанию:
источник
Да, с функциями C99 вы можете сделать это. Это работает без определения новых структур данных или около того и без функции, которая должна решать во время выполнения, как она была вызвана, и без каких-либо вычислительных затрат.
Для подробного объяснения смотрите мой пост на
http://gustedt.wordpress.com/2010/06/03/default-arguments-for-c99/
Jens
источник
Обычно нет, но в gcc Вы можете сделать последний параметр funcA () необязательным с помощью макроса.
В funcB () я использую специальное значение (-1), чтобы указать, что мне нужно значение по умолчанию для параметра 'b'.
источник
Я улучшил ответ Йенса Гастедта так, чтобы:
variadic.h:
Упрощенный сценарий использования:
И с _Generic:
И с выбором имени переменной функции, которую нельзя комбинировать с _Generic:
источник
ДА
Через макросы
3 параметра:
Если вы хотите 4-й аргумент, то нужно добавить дополнительный my_func3. Обратите внимание на изменения в VAR_FUNC, my_func2 и my_func
4 параметра:
Исключение составляет только то, что переменным с плавающей запятой не могут быть заданы значения по умолчанию ( если только это не последний аргумент, как в случае с 3 параметрами ), потому что им нужен период ('.'), Который не принимается внутри аргументов макроса. Но можно найти обходной путь, как показано в макросе my_func2 ( в случае с 4 параметрами )
программа
Вывод:
источник
Да, вы можете делать что-то симулярное, здесь вы должны знать различные списки аргументов, которые вы можете получить, но у вас есть одна и та же функция для обработки всех.
источник
Почему мы не можем сделать это
Дайте необязательному аргументу значение по умолчанию. Таким образом, вызывающая функция не обязательно должна передавать значение аргумента. Аргумент принимает значение по умолчанию. И легко этот аргумент становится необязательным для клиента.
Например,
void foo (int a, int b = 0);
Здесь b необязательный аргумент.
источник