U
Uncle Steve
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.
Yeah.
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?
I didn't say anything about having function return values available
at compile-time. I can't even imagine why someone would want to do
such a thing.
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."
Ok, I guess that's what it says.
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.
That might be true. I have a hash function that could be exactly
tuned to have the optimum number of buckets. In theory.
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.
Yup. Recursive includes are considered harmful to the normal human
mind. Banned in some jurisdictions where programmer-cruelty laws hold
sway.
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.
Or you might want to size your buffers as a percentage of total
physical RAM. There are several scenarios where this would be
convenient.
Regards,
Uncle Steve