Значения по умолчанию для аргументов в функциях C и перегрузка функций в C - PullRequest
16 голосов
/ 07 июня 2010

Преобразование библиотеки C ++ в ANSI C, и кажется, что ANSI C не поддерживает значения по умолчанию для переменных функций, или я ошибаюсь?Я хочу что-то вроде

int funcName(int foo, bar* = NULL);

Кроме того, возможна ли перегрузка функции в ANSI C?

Потребуется

const char* foo_property(foo_t* /* this */, int /* property_number*/);

const char* foo_property(foo_t* /* this */, const char* /* key */, int /* iter */);

Можно, конечно, просто назвать их по-другому, ноЯ привык к C ++, вроде как для перегрузки функций.

Ответы [ 9 ]

25 голосов
/ 07 июня 2010

Нет, Standard C также не поддерживает. Почему вы считаете, что вам нужно конвертировать код C ++ в C? Это может быть довольно сложно - я бы подумал, что написание обёрток будет хорошим решением, если ваш C ++ должен вызываться из C.

19 голосов
/ 01 июня 2012

Тем не менее я нашел "хитрость", чтобы сделать это, если вы используете GCC.

GCC имеет удобное расширение ## для макроса variadic, которое позволяет имитировать аргумент по умолчанию.

Трюк имеет ограничения: он работает только для 1 значения по умолчанию, а аргумент должен быть последним из параметров вашей функции.

Вот рабочий пример.

#include <stdio.h>


#define SUM(a,...) sum( a, (5, ##__VA_ARGS__) )

int sum (a, b)
  int a;
  int b;
{
  return a + b;
}


main()
{

  printf("%d\n", SUM( 3, 7 ) );

  printf("%d\n", SUM( 3 ) );

}

В этом случае я определяю SUM как вызов суммы с вторым аргументом по умолчанию, равным 5.

Если вы вызываете с 2 аргументами (первый вызов в main), он будет предварительно обработан как: сумма (3, (5, 7));

Это означает:

  • 1-й аргумент - 3
  • второй аргумент является результатом последовательности (5, 7) ... которая очевидно 7!

Поскольку gcc умен, это не влияет на время выполнения, так как первый член последовательности является константой и не нужен, он просто отбрасывается во время компиляции.

Если вы вызываете только с одним аргументом, расширение gcc удалит VA_ARGS AND ведущую кому. Таким образом, он предварительно обрабатывается как:

сумма (3, (5));

Таким образом, программа выдает ожидаемый результат:

10
8

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

3 голосов
/ 23 августа 2012

Существует способ поддерживать столько параметров по умолчанию, сколько вам нужно, просто используйте структуру.

// Populate structure with var list and set any default values
struct FooVars {
  int int_Var1 = 1;  // One is the default value
  char char_Command[2] = {"+"};
  float float_Var2 = 10.5;
};
struct FooVars MainStruct;

//...
// Switch out any values needed, leave the rest alone
MainStruct.float_Var2 = 22.8;
Myfunc(MainStruct);  // Call the function which at this point will add 1 to 22.8.
//...

void Myfunc( struct FooVars *MyFoo ) {
  switch(MyFoo.char_Command) {
    case '+':
      printf("Result is %i %c %f.1 = %f\n" MyFoo.int_Var1, MyFoo.char_Command, MyFoo.float_Var2, (MyFoo.float_Var2 + MyFoo.int_Var1);
      break;
    case '*':
      // Insert multiply here, you get the point...
      break;
    case '//':
      // Insert divide here...
      break;
  }
}
3 голосов
/ 07 июня 2010

Насколько я знаю, ANSI C напрямую не поддерживает перегрузку функций или аргументы по умолчанию. Стандартной заменой перегрузки является добавление суффиксов к имени функции, указывающих типы аргументов. Например, в OpenGL суффикс «3fv» к имени функции означает, что функция принимает вектор из трех чисел с плавающей запятой.

Аргументы по умолчанию можно рассматривать как частный случай перегрузки функции.

2 голосов
/ 07 мая 2014

Попробуйте это.

#include <stdio.h>
#include <stdarg.h>

/* print all non-negative args one at a time;
   all args are assumed to be of int type */
void printargs(int arg1, ...)
{
  va_list ap;
  int i;

  va_start(ap, arg1); 
  for (i = arg1; i >= 0; i = va_arg(ap, int))
    printf("%d ", i);
  va_end(ap);
  putchar('\n');
}

int main(void)
{
   printargs(5, 2, 14, 84, 97, 15, 24, 48, -1);
   printargs(84, 51, -1);
   printargs(-1);
   printargs(1, -1);
   return

 0;
}
1 голос
/ 07 июня 2010

Вы не можете так легко, так как C не поддерживает их. Более простой способ получить «поддельную перегрузку» - это использовать суффиксы, как уже было сказано ... значения по умолчанию можно смоделировать с помощью функции переменных аргументов, определяющей количество передаваемых аргументов и программно устанавливающей значение по умолчанию для пропущенного, например:

 aType aFunction(int nargs, ...)
 {
   // "initialization" code and vars
   switch(nargs)
   {
     case 0:
         // all to default values... e.g.
         aVar1 = 5; // ...
         break;
     case 1:
         aVar1 = va_arg(arglist, int); //...
         // initialize aVar2, 3, ... to defaults...
         break;
     // ...
   }
 }

Также можно моделировать перегрузку, используя var args с дополнительной информацией, которую нужно добавить и передать, и экстракодировать ... в основном, воспроизводя минималистичный объектно-ориентированный режим выполнения ... Другое решение (или действительно то же самое, но с другим подходом) может заключаться в использовании тегов: каждый аргумент является парным типом аргумента + аргумент (объединение во всем наборе возможного типа аргумента), есть специальный терминатор (нет необходимости указывать, как много аргументов, которые вы передаете), и, конечно, вам всегда нужно «сотрудничество» с вызываемой функцией, то есть она должна содержать дополнительный код для анализа тегов и выбора фактической функции, которая должна быть выполнена (она ведет себя как своего рода грузоотправитель)

1 голос
/ 07 июня 2010

Ни одно из значений по умолчанию или перегрузка функций не существует в ANSI C, поэтому вам придется решать это по-другому.

0 голосов
/ 27 февраля 2017

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

#include <stdarg.h>
#include <stdio.h>
void baz( int flag, ... )
{
    va_list ap;
    char *bar = "baz"; /* default value */
    va_start( ap, flag );
    if ( flag == 1 )
        bar = va_arg( ap, char * );
    va_end( ap );
    printf( "%s\n", bar );
}
int main( void )
{
    baz( 0 );
    baz( 1, "foo");
    baz( 2 );
    baz( 1, "bar");
    return 0;
}

вывод

baz
foo
baz
bar

если вы посмотрите, например, человека 2 открытым, они скажут

SYNOPSIS
       #include <sys/types.h>
       #include <sys/stat.h>
       #include <fcntl.h>

       int open(const char *pathname, int flags);
       int open(const char *pathname, int flags, mode_t mode);

       int creat(const char *pathname, mode_t mode);

       int openat(int dirfd, const char *pathname, int flags);
       int openat(int dirfd, const char *pathname, int flags, mode_t mode);

но режим на самом деле ... аргумент

0 голосов
/ 07 июня 2010

Вам придется объявлять каждую перегруженную функцию C ++ по-разному в C, потому что C не делает искажение имени . В вашем случае "foo_property1" "foo_property2".

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...