Fonctions à l’intérieur des fonctions en C

Je crée un code similaire à ceci:

#include  double some_function( double x, double y) { double inner_function(double x) { // some code return x*x; } double z; z = inner_function(x); return z+y; } int main(void) { printf("%f\n", some_function(2.0, 4.0)); return 0; } 

Cela comstack parfaitement dans GCC (sans avertissements) mais ne parvient pas à comstackr dans ICC.

La CPI donne:

 main.c(16): error: expected a ";" { ^ main.c(21): warning #12: parsing restarts here after previous syntax error double z; ^ main.c(22): error: identifier "z" is undefined z = inner_function(x); ^ compilation aborted for main.c (code 2) 

Qu’est-ce que je fais mal?

Merci.

(edit) Désolé pour le pauvre exemple. Dans mon code d’origine, j’ai un peu besoin de faire ce genre de choses. J’utilise un intégrateur numérique GSL et j’ai quelque chose comme:

 double stuff(double a, double b) { struct parameters { double a, b; }; double f(double x, void * params) { struct parameters p = (struct parameters *) params; double a = p->a, b = b->b; return some_expression_involving(a,b,x); } struct parameters par = {a,b}; integrate(&f, &par); } 

Et j’ai beaucoup de fonctions avec ce genre de structure: elles sont le résultat d’une intégration de fonctions avec beaucoup de parameters externes. Et les fonctions qui implémentent l’intégration numérique doivent recevoir un pointeur sur une fonction de type:

 double f(double x, void * par) 

J’aimerais vraiment que les fonctions soient nestedes de cette façon afin que mon code ne soit pas encombré de beaucoup de fonctions. Et j’espère que je pourrais le comstackr avec ICC pour accélérer les choses un peu.

Tout le monde vous a donné la réponse canonique “Les fonctions nestedes ne sont pas autorisées en C standard” (leur utilisation dépend donc de votre compilateur).

Votre exemple révisé est:

 double stuff(double a, double b) { struct parameters { double a, b; }; double f(double x, void * params) { struct parameters p = (struct parameters *) params; double a = p->a, b = b->b; return some_expression_involving(a,b,x); } struct parameters par = {a,b}; return integrate(&f, &par); // return added! } 

Puisque vous dites que les fonctions telles que l’intégrateur ont besoin

  double (*f)(double x, void * par); 

Je ne vois pas pourquoi vous avez vraiment besoin de fonctions nestedes. Je m’attendrais à écrire:

 struct parameters { double a, b; }; static double f(double x, void *params) { struct parameters p = (struct parameters *) params; double a = p->a, b = b->b; return some_expression_involving(a,b,x); } double stuff(double a, double b) { struct parameters par = { a, b }; return integrate(f, &par); } 

Le code ci-dessus devrait fonctionner en C89 (sauf s’il ya un problème avec l’initialisation ‘par’ comme ça) ou en C99; cette version du code est pour C99 uniquement, en utilisant un littéral composé pour le paramètre (section 6.5.2.5 Littéraux composés):

 double stuff(double a, double b) { return integrate(f, &(struct parameters){a, b}); } 

Les chances sont excellentes que vous n’ayez que quelques variations sur le type ‘struct parameters’. Vous devez fournir des noms distincts (suffisamment) significatifs pour les différentes fonctions. Vous ne pouvez avoir qu’une seule fonction appelée ” f ” par fichier source.

Le seul petit avantage marginal de la version de fonction nestede est que vous pouvez être sûr qu’aucune autre fonction que celle d’appels de fonctions f . Mais étant donné l’exemple de code, il ne s’agit pas d’un avantage majeur. la définition statique de f signifie qu’aucune fonction en dehors de ce fichier ne peut l’appeler à moins de passer un pointeur sur la fonction.

Les fonctions nestedes sont disponibles en tant qu’extension de langage dans GCC , mais elles ne font pas partie du langage standard. Certains compilateurs ne les autorisent donc pas.

C n’a pas de fonctions nestedes. Les fonctions nestedes de GCC sont une extension du langage.

Votre erreur d’exécution dans GCC est une faute d’orthographe. inner_funcion devrait être inner_function .

Comme mentionné par de nombreuses réponses ci-dessus, les fonctions internes ne sont pas sockets en charge en C, cependant, les classes internes peuvent être utilisées en C ++ pour accomplir une tâche similaire. Malheureusement, ils sont un peu difficiles à utiliser, mais cela pourrait être une option pour vous si la compilation en C ++ ne vous dérange pas.

Exemple non testé:

 double some_function( double x, double y) { struct InnerFuncs { double inner_function(double x) { // some code return x*x; } // put more functions here if you wish... } inner; double z; z = inner.inner_function(x); return z+y; } 

Notez que cette réponse ne doit pas impliquer que je pense que les fonctions internes sont une bonne idée de l’utilisation que vous avez montrée.

Des années plus tard, éditez:

C ++ nous permet maintenant d’utiliser les lambdas en tant que fonctions internes. Dans le cas de mon exemple de jouet ci-dessus, cela ressemblerait beaucoup à ceci:

 double some_function( double x, double y) { auto inner_function = [&]() { return x * x; } double z; z = inner_function (); return z + y; } 

Notez que la variable locale x est automatiquement capturée à l’intérieur du lambda, ce qui est très pratique.

Plus ici: Qu’est-ce qu’une expression lambda en C ++ 11?

Vous utilisez des fonctions nestedes – C ne prend pas en charge de telles choses.

Ce n’est pas un code C valide, les fonctions internes ne sont pas supscopes en C

les définitions de fonctions locales à l’intérieur d’une fonction sont illégales en C.

Les fonctions nestedes ne font pas partie des normes C. Il n’ya donc aucune garantie que cela fonctionnera pour tous les compilateurs et qu’il faut absolument l’éviter.

Au cas où vous vous demandiez comment désactiver les extensions GCC et autres.

Vous pouvez utiliser le drapeau -ansi qui définit essentiellement la norme sur c89 et désactive les fonctionnalités GCC incompatibles avec ISO C90.

Voir la documentation pour plus d’informations. Découvrez aussi le drapeau -std .

Je ne suis pas un expert, mais je suis prêt à parier que cela est explicitement interdit ou indéfini par la spécification C99. Il est donc probablement préférable de s’en tenir à l’écart.