Значения по умолчанию для аргументов в функциях C и перегрузка функций в C

Преобразование С++ lib в 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 */);

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

Ответ 1

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

Ответ 2

Тем не менее, я нашел "трюк", если вы используете GCC.

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

Трюк имеет ограничения: он работает только для 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.

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

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

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

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

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

sum (3, (5));

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

10
8

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

Ответ 3

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

// 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;
  }
}

Ответ 4

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

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

Ответ 5

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

#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;
}

Ответ 6

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

Ответ 7

Вы не можете так легко, так как 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 с дополнительной информацией, которая должна быть добавлена ​​и передана, а extracode... в основном воспроизводит минималистичную объектно-ориентированную среду выполнения... Другое решение (или, действительно, одно и то же, но с другим подходом) могло бы использовать теги: каждый аргумент представляет собой аргумент типа пары + аргумент (объединение всего набора возможных типов аргументов), там есть специальный тег терминатора (нет необходимости указывать, как многие аргументы, которые вы передаете), и, конечно, вам всегда нужно "сотрудничество" с функцией, которую вы вызываете, то есть она должна содержать дополнительный код для анализа тегов и выбора фактической функции (она ведет себя как своего рода диспетчер)

Ответ 8

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

Ответ 9

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

#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

если u ищите, например, man 2 open, они говорят

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);

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