web-dev-qa-db-fra.com

Un prototype de fonction typedef peut-il être utilisé dans les définitions de fonction?

J'ai une série de fonctions avec le même prototype, disons

int func1(int a, int b) {
  // ...
}
int func2(int a, int b) {
  // ...
}
// ...

Maintenant, je veux simplifier leur définition et leur déclaration. Bien sûr, je pourrais utiliser une macro comme ça:

#define SP_FUNC(name) int name(int a, int b)

Mais je voudrais le garder en C, j'ai donc essayé d'utiliser le spécificateur de stockage typedef pour cela:

typedef int SpFunc(int a, int b);

Cela semble bien fonctionner pour la déclaration:

SpFunc func1; // compiles

mais pas pour la définition:

SpFunc func1 {
  // ...
}

ce qui me donne l'erreur suivante:

error: expected '=', ',', ';', 'asm' or '__attribute__' before '{' token

Existe-t-il un moyen de le faire correctement ou est-ce impossible? À ma connaissance de C, cela devrait fonctionner, mais ce n'est pas le cas. Pourquoi?


Remarque, gcc comprend ce que j'essaie de faire, car si j'écris

SpFunc func1 = { /* ... */ }

ça me dit

error: function 'func1' is initialized like a variable

Ce qui signifie que gcc comprend que SpFunc est un type de fonction.

35
bitmask

Vous ne pouvez pas définir une fonction à l'aide d'un typedef pour un type de fonction. C'est explicitement interdit - reportez-vous à 6.9.1/2 et à la note de bas de page associée:

L'identifiant déclaré dans une dé fi nition de fonction (qui est le nom de la fonction) doit avoir un type de fonction, comme spécifié par la partie déclarante de la définition de fonction.

L'intention est que la catégorie de type dans une définition de fonction ne puisse pas être héritée d'un typedef:

typedef int F(void); // type F is "function with no parameters
                     // returning int"
F f, g; // f and g both have type compatible with F
F f { /* ... */ } // WRONG: syntax/constraint error
F g() { /* ... */ } // WRONG: declares that g returns a function
int f(void) { /* ... */ } // RIGHT: f has type compatible with F
int g() { /* ... */ } // RIGHT: g has type compatible with F
F *e(void) { /* ... */ } // e returns a pointer to a function
F *((e))(void) { /* ... */ } // same: parentheses irrelevant
int (*fp)(void); // fp points to a function that has type F
F *Fp; //Fp points to a function that has type F
45

Un typedef définit un type, pas un en-tête (qui est du texte de code source). Vous devez utiliser #define (bien que je ne le recommande pas) si vous devez factoriser le code de l'en-tête.

([Modifié] La raison pour laquelle le premier fonctionne est qu'il ne définit pas un prototype - il définit une variable du type défini par typedef, ce qui n'est pas ce que vous voulez.)

0
user541686