2014-06-14 4 views
2

Je commence à apprendre la programmation fonctionnelle et je voulais voir si je pouvais sortir avec des fermetures en C. Pour reproduire premier exemple de Wikipedia - Closures I codé le code suivant:Fermeture en C - Est-ce que cela fonctionne?

#include <stdio.h> 

void closure (int(** f)(int), int *x) { 
    int fcn(int y) { 
     return *x + y; 
    }; 
    *f = fcn; 
} 

int main() 
{ 
    int x = 1; 
    int(* f)(int); 

    closure(&f, &x); 

    printf("%d", f(2)); 

    return 0; 
} 

Il a été compilé (gcc 4.8.2 sur Ubuntu 14.04.) Et cela fonctionne, il imprime 3. Comme mon manque d'expertise en C (seulement les cours de base sur le collège), ma question est, y at-il quelque chose de grave avec ce code? On m'a enseigné les définitions de fonction doit être globale et je ne m'y attendais pas été à travailler ...

Edit: Et pourquoi est-ce, quand je change la fonction principale comme ceci:

int main() 
{ 
    int x = 1; 
    int(* f)(int); 

    closure(&f, &x); 

    printf("%d", f(2)); 
    printf("%d", f(3)); // the only difference 

    return 0; 
} 

Je reçois Segmentation faute?

Répondre

4

Votre code fonctionne parce que gcc a une extension de langage qui prend en charge les fonctions imbriquées. Cependant, en C standard, vous ne pouvez pas définir une fonction dans une autre fonction.

Gnu Nested Functions

Si vous essayez d'appeler la fonction imbriquée par son adresse après la sortie de la fonction contenant, tous l'enfer se déchaîne. Si vous essayez de l'appeler après la fermeture d'un niveau de portée contenant, et si cela fait référence à certaines variables qui ne sont plus dans la portée, vous pouvez être chanceux, mais il n'est pas sage de prendre le risque. Si, toutefois, la fonction imbriquée ne se réfère à rien qui est hors de portée, vous devriez être en sécurité. Tout d'abord, votre programme appelle un comportement indéfini

+0

Merci pour votre réponse. J'ai édité une question avec un exemple qui ne fonctionne pas (désolé de ne pas l'avoir posté plus tôt). Ne devrait-il pas y avoir quelques problèmes de mémoire comme l'accès aux variables locales hors de portée ou quelque chose de similaire? –

2

En effet, la fonction fcn définie dans la fonction closure est locale. fcn n'existe plus une fois que closure retourne. Ainsi, le printf appel

printf("%d", f(2)); 

invoque un comportement non défini en appelant f(2) parce que f des points à la fonction fcn qui n'est pas portée.

Le langage C n'a pas de fermeture, car les fonctions C ne sont pas des objets de première classe. Cela signifie que les fonctions ne peuvent pas être transmises à d'autres fonctions ou ne peuvent pas être renvoyées à partir d'une fonction. Ce qui est réellement passé ou retourné est un pointeur.

Veuillez noter qu'il existe une différence entre les fonctions imbriquées et la fermeture. Ce que vous voyez est une extension GCC pour nested function. Cela ne fait pas partie de la norme C.

Questions connexes