Предположим, что у меня есть вариационная функция foo(int tmp, ...)
, при вызове функции foo мне нужно знать, сколько аргументов есть. Я знаю два способа узнать, сколько аргументов есть:Использовать вариационные функции в C89 без прохождения числа аргументов или окончательного аргумента?
Используйте последний аргумент при вызове Foo, как -1, так что ваш вызов функции будет выглядеть следующим образом:
foo(tmp, 1, 2, 9, -1)
и когда вы внутри foo и va_arg вызывает -1, вы знаете, что вы прочитали все аргументы функции.Добавить еще один аргумент в foo, где у программиста будет общее количество аргументов, поэтому у вас будут вызовы для foo следующим образом:
foo(tmp, 5, 1, 2, 3, 4, 5)
илиfoo(tmp, 2, 7, 8)
Я привык следовать первому пути и однажды имел следующую ошибку. С кодом:
expr_of_type(expr, boolexpr_e, newtable_e, nil_e, -1)
где expr_of_type был VARIADIC функция и была проверка, если выражение (первый аргумент) был один из следующих типов (boolexpr_e или new_table_e или nil_e имели все типы перечислимого типа). Я один случайно написал:
expr_of_type(expr, boolexpr_e, newtable_e, nil_e -1)
Я забыл запятую между nil_e и -1, потому что nil_e был перечисляемого типа, nil_e - 1 является действительным выражением и потому nil_e не было 0 данная функция VARIADIC при попытке get expr_of_type аргументы не нашли -1 в качестве последнего аргумента и продолжали поиск, создав ошибку, которая потребовала мне времени, чтобы узнать.
Я тоже не считаю, что второй способ хорош, потому что при добавлении или удалении еще одного аргумента из вариационной функции вам нужно изменить параметр, содержащий количество общих аргументов.
В поисках лучшего способа использования/создания вариационных функций я нашел variadic macros, который может решить ошибку, которую я использовал при первом использовании. Но переменные макросы доступны для стандарта C99. Я искал лучший способ использовать/создавать вариативные функции в C89. Есть идеи?
Использование 'enum' или' const int 'приведет к такой же проблеме при забывании запятой? –
Нет, не будет. Если у вас есть 'const int VARARG_SENTILEL = -1;', когда вы забыли запятую, у вас будет что-то вроде этого 'nil_e VARARG_SENTINEL', которое дает ошибку компиляции. То же самое происходит, когда вы используете 'enum {VARARG_SENTINEL = -1};'. С обоими решениями при забывании запятой это похоже на 'number1 number2' (например,' 2 3'), который является недопустимым выражением, но при использовании -1, как я использовал, у вас будет 'номер-1', который является действительное выражение. –