You're making this too easy. What could be cleaner than a variable
declaration outside of main() which also initializes it to the value it
should have before main() is called?
Ok, so my impression now is that by "cleaner," you mean that such
reduces keyboard typing redundancy by having the value population appear
alongside the declaration, thus avoiding typing the identifier's name
again within an init() function.
I'm fully aware that I can
assign a value to a variable any time I write code or macros to do it,
but there are certain kinds of application parameters, for instance,
which you may derive empirically, and assign once. I should think
that most programmers know about these types of variables.
Ah, now this gives me the impression that not only are you interested in
restoring saved settings, but that you'd _also_ like to be able to
compute things using C functions, and have those computation results
available at compile-time. Perhaps something like declaring an array
with a number of elements which is 'pow(5, 6)'. Do I understand your
wish correctly?
It could do just about anything if it was a C function, couldn't it?
Perhaps not in a standard, portable sense. As an example, we have
n1256.pdf, section 6.5.2.2, point 1:
"The expression that denotes the called function...shall have type
pointer to function returning void or returning an object type other
than an array type."
This is fine, and I've in fact done just that in code I've written
previously. But see above.
It's also nicely symmetrical if you have a save_settings(). The
suggested init() might as well be called restore_settings() or
load_settings().
But your "see above" suggests (to me) that you are interested in
computations which are needed in order to affect _compile-time_
decisions, rather than _run-time_ decisions.
I'm big on macros, but sometimes they clutter up the code with
redundant code blocks that are deader than a doornail. Maybe the
compiler will weed them out with global CSE, maybe not. If they
aren't in the code to begin with, they can't possibly get into the
instruction cache.
One possible way to achieve _something_like_ the _look_ of the
declarations calling functions might be the following example "uncle.c":
#ifndef GLOBAL_INITS
# define TYPE(x) x
# define INIT(x) {0}
#else
# undef TYPE
# define TYPE(x)
# undef INIT
# define INIT(x) x
#endif /* GLOBAL_INITS */
#ifndef GLOBAL_INITS
#include <stdio.h>
#endif /* GLOBAL_INITS */
/*** Globals */
TYPE(int) saved_setting = INIT(get_saved_setting());
TYPE(int) saved_setting2 = INIT(get_saved_setting2());
#ifndef GLOBAL_INITS
int get_saved_setting(void) {
/* TODO: Actually fetch the saved setting */
return 3;
}
int get_saved_setting2(void) {
/* TODO: Actually fetch the saved setting */
return 5;
}
void init(void) {
#define GLOBAL_INITS 1
#include "uncle.c"
#undef GLOBAL_INITS
return;
}
int main(void) {
init();
printf("saved_setting: %d\n", saved_setting);
printf("saved_setting2: %d\n", saved_setting2);
return 0;
}
#endif /* GLOBAL_INITS */
That's still kind of ugly.
However this would not help with a wish to call C functions in order to
compute something which needs to influence compile-time decisions, such
as the size of an array declared at file-scope. I think that folks
usually have a separate C program perform such computations, then output
C source, which is then compiled with the rest of your code; code
generation.