views:

152

answers:

5

This is the way I get to prevent funA,funB,funC, etc.. for being used before init

#define INIT_KEY 0xC0DE //any number except 0, is ok

static int initialized=0;

int Init()
{
  //many init task
  initialized=INIT_KEY;
}


int funA()
{
 if (initialized!=INIT_KEY) return 1;
 //..
}

int funB()
{
 if (initialized!=INIT_KEY) return 1;
 //..
}

int funC()
{
 if (initialized!=INIT_KEY) return 1;
 //..
}

The problem with this approach is that if some of those function is called within a loop so "if (initialized!=INIT_KEY)" is called again, and again, although it's not necessary.

It's a good example of why constructors are useful haha, If it were an object I would be sure that when it was created, initialization was called, but in C, I don't know how to do it.

Any other ideas are welcome!

+5  A: 

Use pointer to function.

At construct time, point the functions at the function that does the required initialization, then updates the function pointers to point to the actual functions that do the work.

I have done this with arrays of pointer to member functions in a class. The class has an internal integer which says what state the object it in. The integer is used to subscript into the array of pointer to member functions... State 0 does the init. State 1, does the work, State 2 sets things back to state 1.

It worked very cleanly.

EvilTeach
I like that, I imagine a little ugly code, but I will try it, if there is no other surprising idea, it could be a right answer, thanks
Hernán Eche
Exactly my favorite idea. You can even do a function does this for first call and that for 2nd call :O
Nyan
mmmm I tried to implement I am not seeing somethng or there is a paradox here because I have to initialize the function pointers..
Hernán Eche
yep.in the constructor, init the pointers to the function that does the INIT_KEY stuff. In the INIT_KEY function, init the pointers to the function to do the work in func_a, func_b, func_c
EvilTeach
+1  A: 

Put your functions inside a structure (use function pointers to access them). Provide a "construct" function to create that structure and assign the correct function addresses in the structure. Almost the same idea as EvilTeach.

Ioan
yes same idea :)
Hernán Eche
Well, not exactly the same. If there's a "construct time", there wouldn't be a need to call your initialization function; you could just initialize function pointers with the correct addresses, etc. Using a struct containing the function pointers seemed similar to what you were looking for to imitate classes with a constructor.
Ioan
+1  A: 

You can think about different solutions. In the loop, no matter the chosen solution, some extra code will be always executed (at best behind the scenes) to prevent the functions to be executed. You could skip in the loop the execution of funX, but it would be extra code to check if funX can be executed, placed differently.

Since commonly initialization is done before other task, this is a strange problem, or a misnaming (you should not call it initialization).

If you want, the functions can call the initializer by themselves, like

if (!initialized) initialize();

Always extra code, and the !initialized will be always false from then on.

But the way to avoid to check again and again is to call explicitly the initialization in the correct place, before the game begins to play for real. (Otherwise don't call it initialization).

If it were an object, ... you don't need object for this. To "trig" a constructor, you must create the object (at least, in many OO languages) with, say, new MyClass() or "declaring it"; here the call to "new" (that is not a call, but for this speech we can think this way) or the "declaration" is changed into a call to an explicit initializer. Your apparently simple

Object a;
// ...
a.method(); //or

Object *a = new Object();
// ...
a->method();

would be

init()
// ...
funA();

Even if this example does not "match" your "need", it should make clear that an explicit initializer is not so tremendously bad and OO languages really are not necessary to "fix" this problem.

You can control when you can call those funcs, so you don't need checking at all; it happens in many libraries that require first a call to special init function before you can use them, or "odd" behaviours must be expected.

ShinTakezou
+4  A: 

You could use some kind of assertions utilizing some preprocessor macros:

#ifdef DEBUG
#  define ENSURE_INITIALIZED(obj) \
     do { \
         if (obj->initialized != INIT_CODE) { \
             fprintf (stderr, "Object %p not initliaized (%s:%d)\n", obj, __FILE__, __LINE__); \
             abort (); \
         } \
     } while (0)
#else
#  define ENSURE_INITIALIZED(obj)
#endif

voif foo (Object *obj) {
    ENSURE_INITIALIZED (obj);
}

This will check for initialization code but only in debug builds - in production builds it will evaluate to no-op.

Calling abort will abnormally terminate program, typically leaving a core dump, or interrupting program when run in debugger.

el.pescado
+1  A: 

A solution would be to do the initialization like this (in each file):

static int initResult = Init();

When program will start, those static variables will be initialized automatically and the function will be called.

IMPORTANT NOTE: The order of the initialization is undefined if you need to do such initializations in more than one file (usually the linking order of the objects dictates the order of the initialization - but there is no rule for that). So you must be careful when doing this.

Iulian Şerbănoiu
+1 for the important note
Hernán Eche
this won't work in C...
Spudd86
@spudd86 - you are right - I got carried away
Iulian Şerbănoiu