Home > Net >  C pointer changes after non-assigning addition
C pointer changes after non-assigning addition

Time:02-15

I am trying to understand how closures could be implemented in a language like C.

Currently I want to create an adder function that takes an int, and returns another function that also takes an int param. Invoking the returned function should result in the sum of the two parameters.

Here's the pseudocode example:

fn adder(int lhs) {
    return fn (int rhs) {
        return lhs   rhs
    }
}

Since nested functions are not available in standard C, I thought I could implement them by passing states. Here's my C implementation:

#include <stdio.h>

typedef struct
{
    int *a; // This attribute should be a pointer as in my
            // ideal interpretation of closures, the state of
            // the parent function should be mutable within the child
} ClosureState;

int adder_inner(ClosureState state, int b)
{
    printf("a = %d\n", *state.a);
    return *state.a   b;
}

ClosureState make_adder(int a)
{
    ClosureState state = {
        .a = &a};

    return state;
}

int main()
{
    ClosureState adder_state = make_adder(5);
    int res1 = adder_inner(adder_state, 5);
    int res2 = adder_inner(adder_state, 10);
    int res3 = adder_inner(adder_state, 50);

    printf("%d, %d, %d\n", res1, res2, res3);
    return 0;
}

The problem: The adder_state object seems to be modified after every invocation of adder_inner but I don't understand why as *state.a is never reassigned.

The output of the code above is:

$ clang -o clj clj.c && ./clj
a = 5
a = 10
a = 50
10, 20, 100

CodePudding user response:

There is no reason for ClojureState (ClosureState) to hold a pointer. It will be much easier if it just holds the int itself:

#include <stdio.h>

typedef struct
{
    int a; // No need for a pointer, the value can still be
           // changed in adder_inner() if needed.
} ClosureState;

int adder_inner(ClosureState *state, int b)
{
    printf("a = %d\n", state->a);
    return state->a   b;
}

ClosureState make_adder(int a)
{
    ClosureState state = {
        .a = a};

    return state;
}

int main()
{
    ClosureState adder_state = make_adder(5);
    int res1 = adder_inner(&adder_state, 5);
    int res2 = adder_inner(&adder_state, 10);
    int res3 = adder_inner(&adder_state, 50);

    printf("%d, %d, %d\n", res1, res2, res3);
    return 0;
}```
  • Related