views:

226

answers:

9

Is there a way to pass the current state of a function into another function in C/C++? I mean all the parameters and local variables by current state. For example:

void funcA (int a, int b)
{
    char c;
    int d, e;
    // Do something with the variables.
    // ...
    funcB();
    // Do something more.
}

void funcB()
{
    // funcB() should be able to access variables a,b,c,d & e
    // and any change in these variables reflect into funcA().
}

The code is in bad shape if there is a need for funcB() kind of functions. But can it be achieved?

This can help if someone is starting to re-factor a long method with multiple parameters.

+1  A: 

No there isn't, in principle the data is all available, it's all on the stack, but C provides no mechanism to access them, unless you start mucking about with inline assembly and pointers and the like. Not something you want to be doing. Better to just pass what you need.

wich
+2  A: 

Create a struct to hold all the state you care about.

Write both functions in in terms of the struct; that is, they take as their only parameter an instance of the struct, and all state is saved in the struct.

struct foo {  int d; int e; char c ; } fooinstance;

void afunc( struct foo fi);
void bfunc( struct foo fi);

void afunc( struct foo fi ) {
  // do stuff with fi
  f1.d += fi.e ;
  fi.c++;
  // call b
  b(fi);
}

Then pass the struct instance from a to b. More efficient would be to pass a pointer to the struct, but passing the struct will work.

tpdi
+6  A: 

Introduce a common struct.

struct State {
    char c;
    int d,e;
};

void funcA(int a, int b){
    State s;
    s.d = 1234; // ...
    // ...
    funcB(s);
}

void funcB(State& s)
{
    //...
}
Notinlist
+1  A: 

This can help if someone is starting to re-factor a long method with multiple parameters.

To beat this particular problem, you could use objects and just bind in constructor some of common used parameters to object's members. And than make your functions (that accept these long lists of parameters) member-functions.

Alexander Poluektov
A: 

Doing something like this would break modularity and the whole purpose of creating functions. funcB would only be callable by certain other functions, specifically those that define the variables it depends on. This would not be at all clear to someone writing new code calling funcB.

As others have suggested, I would either create a struct just for this purpose or pass all the needed variables by reference to make it clear what funcB relies on.

Aaron
+1  A: 

The best solution is to put variables in a structure and pass this structure by reference to other function. Though, there is another solution you can use macros. Macros are able access any variable you have in the same scope, but I'm not recommending this approach.

AndreiM
+4  A: 

gcc supports a Pascal-like extension to C, namely nested functions, e.g.

#include <stdio.h>

int main(void)
{
    int a = 1, b = 2;

    void foo(void)
    {
        printf("%s: a = %d, b = %d\n", __FUNCTION__, a, b);
    }

    printf("%s: a = %d, b = %d\n", __FUNCTION__, a, b);

    foo();

    return 0;
}

Compile this with --nested-functions:

$ gcc -Wall --nested-functions nested.c -o nested

and then run it:

$./nested
main: a = 1, b = 2
foo: a = 1, b = 2

Of course this is non-portable but if you are only using gcc and you have too much legacy code to re-write then this might be a good solution.

Paul R
+3  A: 

Another one that may be more elegant than the first. It uses a struct with static members.

struct SomeAlgo {
    SomeAlgo()
    : c(0), d(0), e(0) // Initialize common variables
    { }
    void funcA(int a,int b)
    {
        c = 1234; //...
        // ...
        funcB();

    }
    void funcB() // You may put it in the private section.
    {
        // Simply use c,d,e here.
    }
private:
    char c;
    int d,e;
};

Usage

SomeAlgo alg;
alg.funcA(3,4);

EDITED: Made members not static. Better that way.

Notinlist
`static` behaves badly with `MultiThread` though, so keep that in mind.
Matthieu M.
@Matthieu M.: Static variables inside functions are not safe, but there is no problem with static member variables which are initialized before the running of main().
Notinlist
The problem is that if two concurrent threads want to use this function, you now need some locking, why make them static ? it would be fine if you had to build an object!
Matthieu M.
True. All stuff should be not static with this solution.
Notinlist
A: 

What you probably want to do, is: encapsulate your functions into a class and create a singleton instance of it. The state you want to share between those functions is what technically happens in OOP by instantiating objects and invoke methods on them.

So if C++ is an option (as C has no OOP) I would recommend going with that solution.

Another approach would be to use lambdas/closures but that is not an option in C/C++ because it does not support those language constructs.

Edit: Only use singletons if you know how to handle these correctly throughout your code...

hurikhan77
Wow. It never ceases to amaze me how some people will answer "you need a singleton" regardless of the question asked.
jalf
@jalf yes you're right, Singletons can be dangerous if not used wisely or in a correct context. Good point. +1
hurikhan77