Slaven Glumac
Slaven Glumac

Reputation: 553

Closure in C - Does this work?

I am starting to learn functional programming and wanted to see if I could get away with closures in C. In order to reproduce first example from Wikipedia - Closures I coded up the following code:

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

It was compiled (gcc 4.8.2. on Ubuntu 14.04.) and it works, it prints out 3. Since the lack of my expertise in C (only basic courses on college), my question is, is there something seriously wrong with this code? I was taught function definitions should be global and I was never expecting this to work...

Edit: And why is it, when I change the main function like this:

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

    closure(&f, &x);

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

    return 0;
}

I get Segmentation fault?

Upvotes: 2

Views: 1660

Answers (2)

Leo Zhuang
Leo Zhuang

Reputation: 489

Your code works because gcc has a language extension that supports nested functions.

However, in standard C, you cannot define a function within another function.

Gnu Nested Functions

If you try to call the nested function through its address after the containing function exits, all hell breaks loose. If you try to call it after a containing scope level exits, and if it refers to some of the variables that are no longer in scope, you may be lucky, but it's not wise to take the risk. If, however, the nested function does not refer to anything that has gone out of scope, you should be safe.

Upvotes: 4

ajay
ajay

Reputation: 9680

First of all, your program invokes undefined behaviour. That's because the function fcn defined in the function closure is local to it. fcn no longer exists once closure returns. So the printf call

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

invokes undefined behaviour by calling f(2) because f points to the function fcn which is not in scope.

The C language does not have closure and that's because functions in C are not first-class objects. What this means is functions cannot be passed to other functions or cannot be returned from a function. What actually gets passed or returned is a pointer to it.

Please note that there is a difference between nested functions and closure. What you see is a GCC extension for nested function. It is not part of the C standard.

Upvotes: 2

Related Questions