BartC said:
Sometimes it's better to explicitly initialise the data, by signalling this
via one of the arguments. For example:
fn(-1); /* tell fn to initialise */
fn(n); /* ordinary call */
Of course you need to choose a value that would not normally be passed (as
in -1 here).
This can have better control, and you can also re-initialise later.
[...]
That could work (assuming a distinguished value is available),
but I wouldn't do it that way.
Instead, I'd provide a separate initialization function that needs
to be called before calling fn(). The caller can then write:
init_fn();
fn(n);
and not have to worry about the fact that I've chosen -1, for some
reason, as a value that makes fn() behave completely differently
than it normally does.
Or I might provide a reset_fn() function to performs the
initialization explicitly, and have fn() itself use a static object
in fn() so it can implicitly initialize itself on the first call
(as others have suggested here). This guarantees that fn() is
never called without first being initialized, but allows you to
reinitialize if necessary. It keeps the normal case as simple
as possible while permitting other cases.
And if more functions depend on the initialization, the static
data can be moved to file scope (in a separately compiled .c file
so it's still invisible to outside callers), and each function can
check it before doing its thing.