web-dev-qa-db-fra.com

Valeurs par défaut des arguments dans les fonctions C et surcharge des fonctions dans C

Conversion d'une librairie C++ en ANSI C et il semble que si ANSI C ne prend pas en charge les valeurs par défaut pour les variables de fonction ou si je me trompe?

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

De plus, la surcharge de fonctions est-elle possible dans le C ANSI?

Aurait besoin

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

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

Bien sûr, je pourrais les nommer différemment, mais comme je suis habitué à C++, je suis un peu habitué à surcharger la fonction.

15
inquam

Non, la norme C ne prend pas en charge non plus. Pourquoi pensez-vous que vous devez convertir votre code C++ en C? Cela pourrait devenir assez compliqué - J'aurais pensé que l'écriture de wrappers serait la solution, si votre C++ devait être appelé depuis le C.

25
anon

Néanmoins, j'ai trouvé un "truc" à faire si vous utilisez GCC.

GCC a une extension ## très pratique sur la macro variadique qui vous permet de simuler un argument par défaut.

L'astuce a des limites: elle ne fonctionne que pour 1 valeur par défaut et l'argument doit être le dernier de vos paramètres de fonction.

Voici un exemple de travail.

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

}

Dans ce cas, je définis SUM comme un appel à additionner, le deuxième argument par défaut étant 5.

Si vous appelez avec 2 arguments (premier appel dans main), il sera pré-traité comme suit: Sum (3, (5, 7));

Ça signifie:

  • 1er argument est 3 
  • le deuxième argument est le résultat de la séquence (5, 7) ... qui est évidemment 7!

Comme gcc est astucieux, cela n’a aucun effet sur le temps d’exécution car le premier membre de la séquence est une constante et n’est pas nécessaire, il sera simplement ignoré au moment de la compilation.

Si vous appelez avec un seul argument, l'extension gcc supprimera les VA_ARGSETle coma principal. Donc, il est prétraité comme:

somme (3, (5));

Ainsi, le programme donne le résultat attendu:

10
8

Donc, cela simule parfaitement (avec les limitations de macro habituelles) une fonction avec 2 arguments, le dernier étant optionnel avec une valeur par défaut appliquée si non fournie.

18
user941239

Pour autant que je sache, ANSI C ne prend pas directement en charge la surcharge de fonctions ou les arguments par défaut. Le substitut standard à la surcharge ajoute des suffixes au nom de la fonction indiquant les types d'argument. Par exemple, dans OpenGL, un suffixe "3fv" pour un nom de fonction signifie que la fonction prend un vecteur de trois floats.

Les arguments par défaut peuvent être considérés comme un cas particulier de surcharge de fonctions.

3
Amnon

Il existe un moyen de prendre en charge autant de paramètres par défaut que vous avez besoin, utilisez simplement une structure.

// 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
John Ritchie

Essaye ça.

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

Ni la valeur par défaut ni la surcharge de fonctions n'existent dans ANSI C, vous devrez donc les résoudre différemment.

1
Hans Insulander

Vous ne pouvez pas si facilement puisque C ne les supporte pas. Le moyen le plus simple d’obtenir une "fausse surcharge" consiste à utiliser des suffixes, comme déjà dit ... les valeurs par défaut pourraient être simulées à l’aide de la fonction arguments variables, en spécifiant le nombre d’arguments passés et en donnant par défaut aux arguments manquants, par exemple:

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

La surcharge peut également être simulée à l’aide de var arguments avec des informations supplémentaires à ajouter et à transmettre, ainsi que des extracodes ... reproduisant en principe une exécution minimaliste orientée objet ... Une autre solution (ou même identique mais avec une approche différente) pourrait être: using tags: chaque argument est un type d’argument paire + argument (une union sur l’ensemble des types d’arguments possibles), il existe une balise de terminaison spéciale (inutile de spécifier le nombre d’arguments que vous passez), et bien sûr vous avez toujours besoin "collaboration" de la fonction que vous appelez, c'est-à-dire qu'il doit contenir du code supplémentaire pour analyser les balises et choisir la fonction à exécuter (il se comporte comme une sorte de répartiteur)

1
ShinTakezou

Vous devrez déclarer chaque fonction surchargée C++ différemment en C, car C ne fait pas nommer mangling . Dans votre cas, "foo_property1" "" foo_property2 ".

0
INS