Non-constant initializers

  • Thread starter Fred the Freshwater Catfish
  • Start date
F

Fred the Freshwater Catfish

Or, rather than using a non-constant initializer, you can call a routine
from main() that initialize the objects.

That's a pretty good idea, but I was looking for something convenient
to set-up global-scope variables in a library. No big deal, but I
thought I could be clever about it.



Fred the Freshwater Catfish
 
S

Seebs

That's a pretty good idea, but I was looking for something convenient
to set-up global-scope variables in a library. No big deal, but I
thought I could be clever about it.

Idle side question:

There's this one guy who rotates names occasionally and asks questions
that feel a lot like this, always using an invalid address, and who rotates
user agents every time he does... And who hasn't posted for a bit. Anyone
getting that sort of vibe from this? (Previous names include, but are not
limited to, "Uno" and "Phred Phungus".)

-s
 
K

kym

In comp.arch Fred the Freshwater Catfish said:
That's a pretty good idea, but I was looking for something convenient
to set-up global-scope variables in a library. No big deal, but I
thought I could be clever about it.

On some platforms its the linker that's responsible for once-only
runtime initialisations. If you name a routine in a special way,
or make sure it's in a code segment with a special name, the linker
sets up code to ensure the code gets called before main(). No need
for static "has it been done yet" variables or explicit calls.

This is how gnu C++ compilers typically arrange for global initialisations.

Unlike the idea of calling C++ from C (which usually won't work), just
hanging off this hook generally does work -- if you can find the documentation.
 
K

kym

In comp.arch Columbus sailed the ocean China Blue said:
Unfortunately this solution is not guarenteed to be available on all platforms.

That's the agreed meaning of "on some platforms", yes.

---
Scientists are always changing their story and as a Conservative, I
have no tolerance for ambiguity. It proves that all science is lies
and the only thing we can trust is right wing rhetoric.
-- BONZO@27-32-240-172 [86 nyms and counting], 14 Jan 2011 14:46 +1100

CORRECTION: True science, (remember that?) can be trusted, but this "science"
is ALL LIES!
-- BONZO@27-32-240-172 [86 nyms and counting], 19 Feb 2011 14:46 +1100
 
F

Fred the Freshwater Catfish

That's the agreed meaning of "on some platforms", yes.


Yeah. I know gcc supports constructor and destructor function
attributes, with some sort of "priority" ranking, but I haven't fooled
with it enough to make it work. I don't know how other compilers fare
in this respect, but it seems like the kind feature that gets
implemented differently by each compiler. I might end up using
zero-length arrays in structure definitions if I find it's popular
enough, but I'm really trying not to make my application require weird
stuff just to compile, or in fact to tie my application to gcc.



Fred the Freshwater Catfish
 
U

Uncle Steve

Idle side question:

There's this one guy who rotates names occasionally and asks questions
that feel a lot like this, always using an invalid address, and who rotates
user agents every time he does... And who hasn't posted for a bit. Anyone
getting that sort of vibe from this? (Previous names include, but are not
limited to, "Uno" and "Phred Phungus".)

I could say I'm not related to whomever you're referring to, but would
anyone care?

To my recollection, I've posted to comp.arch and comp.lang.c on a mere
handful of occasions in the ten or so years I've been posting to
Usenet. What may be happening here is you may be annoyed at my parody
of code examples in netnews messages.



Regards,

Uncle Steve
 
U

Uncle Steve

Are you the same person as "Fred the Freshwater Catfish"? Or are you
another person who also wishes to accomplish this type of thing?

Apparently I've been caught out. Now my stalkers will know that I
secretly lurk in c.l.c. occasionally.
I'm looking to seed a few critical global variables with
run-time computed values. Obviously, this will be the product of a
function call. I would like to declare:

int foops[] = howmuchfoo(void);

and have everything work as I expect...

Some more questions:

- When do you wish this initialization to occur? Prior to main()?

In a perfect world.
- Could you employ and enjoy an init() function which would initialize
these objects, then make that the first call inside main()?

- In your code example, is howmuchfoo() supposed to be returning an
array of 'int' or a single 'int'?

I don't see how that's relevant to the question.
- Is your request a matter of being able to read, in your code, what
will be computed for an object in the immediate vicinity of the object,
rather than in another place (such as an init() function)?

That all depends on what kind of data the variables are going to hold.
One time, I might want to save/restore window size and positioning,
and in another place, the volume setting of application sounds. It is
impossible to say, a priori, what variables will be used/set where, at
least at this stage of the design process.
- Would you be willing to use macros to accomplish this?

I'll think about it.



Regards,

Uncle Steve
 
E

Eric Sosman

[...] I would like to declare:

int foops[] = howmuchfoo(void);

and have everything work as I expect...
[...]

- In your code example, is howmuchfoo() supposed to be returning an
array of 'int' or a single 'int'?

I don't see how that's relevant to the question.

The point is that the one-line fragment you posted is not
valid C, not if `howmuchfoo(void)' is any kind of function at all.
(If `howmuchfoo' is a function-like macro, it can of course expand
at compile-time into pretty much anything.) But if it's a function
call, the fragment is meaningless regardless of what scope it appears
in -- which means that by exhibiting it you have conveyed no meaning
to anyone. It is as if you had offered `int foops[] = !<petunia/>;'
and expected people to understand you. If you want to be understood,
you'll have to explain yourself more clearly.

Something that strikes me as odd is that you(?) started this
thread with the statement that you(?) sought a "maximally portable"
solution. Why, then, all this haring off after blatantly non-
portable approaches? Lost sight of the objective, or just trolling?
 
U

Uncle Steve

On 5/12/2011 6:22 PM, Uncle Steve wrote:
[...] I would like to declare:

int foops[] = howmuchfoo(void);

and have everything work as I expect...
[...]

- In your code example, is howmuchfoo() supposed to be returning an
array of 'int' or a single 'int'?

I don't see how that's relevant to the question.

The point is that the one-line fragment you posted is not
valid C, not if `howmuchfoo(void)' is any kind of function at all.

Yes, and I figured out that I had a misconception of how gcc handles
non-constant initilizers. I've already admitted that I'm not coding
anything specific at the moment, and instead /contemplating/ an
approach to solving a particular problem, of which variable
initialization is a part.
(If `howmuchfoo' is a function-like macro, it can of course expand
at compile-time into pretty much anything.) But if it's a function
call, the fragment is meaningless regardless of what scope it appears
in -- which means that by exhibiting it you have conveyed no meaning
to anyone. It is as if you had offered `int foops[] = !<petunia/>;'
and expected people to understand you. If you want to be understood,
you'll have to explain yourself more clearly.
l
I think that I'm being clear enough here. The problem may be that
the subtleties associated with these issues are difficult to
articulate. If you don't like my humor, say so. I don't have a
pathological condition that requires that I include funnyisms in the
text, but it does amuse me to do so.
Something that strikes me as odd is that you(?) started this
thread with the statement that you(?) sought a "maximally portable"
solution. Why, then, all this haring off after blatantly non-
portable approaches? Lost sight of the objective, or just trolling?

I don't see where I've committed to any "blatantly" non-portable
approaches. In actual point of fact I've been asking about certain
compiler features and their actual prevalence in the field. I'm sorry
I don't know any real programmers IRL, with whom I might have these
talks with instead.



Regards,

Uncle Steve
 
U

Uncle Steve

Apparently I've been caught out. Now my stalkers will know that I
secretly lurk in c.l.c. occasionally.

If you are, that doesn't bother me. :) I was merely confirming as I
found the use of different posting names slightly confusing. So getting
back to the C...
Right.
I'm looking to seed a few critical global variables with
run-time computed values. Obviously, this will be the product of a
function call. I would like to declare:

int foops[] = howmuchfoo(void);

and have everything work as I expect...

Some more questions:

- When do you wish this initialization to occur? Prior to main()?

In a perfect world.

Ok. So now: Why? (Please see next response.)
No answer to this one? If the very first thing main() does is to call
an init() which populates your globals' values, then that init() makes
for a nicely-readable section of code to gather these items into one place.

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? 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.
Well it's an opportunity to suggest that C functions do not return
arrays, as far as I know. If howmuchfoo() was a macro that expanded to
an initializer list, then I believe that'd be fine.

It could do just about anything if it was a C function, couldn't it?
My question there wasn't too clear and I apologize. What I am trying to
understand is why you might be inclined to avoid something like the
init() suggestion. Is it a matter of:

int saved_setting = get_saved_setting();

looking nicer, to you, at file scope, than:

int saved_setting;
/* ... */
void init(void) {
saved_setting = get_saved_setting();
/* ...Other globals populated... */
return;
}
/* ... */
int main(void) {
/* Populate globals */
init();
/* ... */
}

?

This is fine, and I've in fact done just that in code I've written
previously. But see above.
Ok. Good fortune to you. :)

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.



Regards,

Uncle Steve
 
S

Shao Miller

Apparently I've been caught out. Now my stalkers will know that I
secretly lurk in c.l.c. occasionally.

If you are, that doesn't bother me. :) I was merely confirming as I
found the use of different posting names slightly confusing. So getting
back to the C...
I'm looking to seed a few critical global variables with
run-time computed values. Obviously, this will be the product of a
function call. I would like to declare:

int foops[] = howmuchfoo(void);

and have everything work as I expect...

Some more questions:

- When do you wish this initialization to occur? Prior to main()?

In a perfect world.

Ok. So now: Why? (Please see next response.)

No answer to this one? If the very first thing main() does is to call
an init() which populates your globals' values, then that init() makes
for a nicely-readable section of code to gather these items into one place.
I don't see how that's relevant to the question.

Well it's an opportunity to suggest that C functions do not return
arrays, as far as I know. If howmuchfoo() was a macro that expanded to
an initializer list, then I believe that'd be fine.
That all depends on what kind of data the variables are going to hold.
One time, I might want to save/restore window size and positioning,
and in another place, the volume setting of application sounds. It is
impossible to say, a priori, what variables will be used/set where, at
least at this stage of the design process.

My question there wasn't too clear and I apologize. What I am trying to
understand is why you might be inclined to avoid something like the
init() suggestion. Is it a matter of:

int saved_setting = get_saved_setting();

looking nicer, to you, at file scope, than:

int saved_setting;
/* ... */
void init(void) {
saved_setting = get_saved_setting();
/* ...Other globals populated... */
return;
}
/* ... */
int main(void) {
/* Populate globals */
init();
/* ... */
}

?
I'll think about it.

Ok. Good fortune to you. :)
 
J

James Kuyper

22 PM, Uncle Steve wrote:
[...] I would like to declare:

int foops[] = howmuchfoo(void);

and have everything work as I expect...
[...]

- In your code example, is howmuchfoo() supposed to be returning an
array of 'int' or a single 'int'?

I don't see how that's relevant to the question.

The point is that the one-line fragment you posted is not
valid C, not if `howmuchfoo(void)' is any kind of function at all.

Yes, and I figured out that I had a misconception of how gcc handles
non-constant initilizers. I've already admitted that I'm not coding
anything specific at the moment, and instead /contemplating/ an
approach to solving a particular problem, of which variable
initialization is a part.
(If `howmuchfoo' is a function-like macro, it can of course expand
at compile-time into pretty much anything.) But if it's a function
call, the fragment is meaningless regardless of what scope it appears
in -- which means that by exhibiting it you have conveyed no meaning
to anyone. It is as if you had offered `int foops[] = !<petunia/>;'
and expected people to understand you. If you want to be understood,
you'll have to explain yourself more clearly.
l
I think that I'm being clear enough here.

You think incorrectly. howmuchfoo() can't be a function call. It could
be a function-like macro, but if so, the possibilities are too
open-ended to be discussed in the abstract; we need information about
the nature of that macro before your question can be addressed.
... The problem may be that
the subtleties associated with these issues are difficult to
articulate. If you don't like my humor, say so.

It has nothing to do with your sense of humor.

....
I don't see where I've committed to any "blatantly" non-portable
approaches. In actual point of fact I've been asking about certain
compiler features and their actual prevalence in the field.

By definition, compiler features mandated by the standard are available
on every single fully conforming implementation. Therefore, code which
relies on any feature that is less than universally prevalent (such as
zero-length arrays) is non-portable.
 
S

Shao Miller

in -- which means that by exhibiting it you have conveyed no meaning
to anyone. It is as if you had offered `int foops[] = !<petunia/>;'
and expected people to understand you.

LOL! It's raining outside. Thanks for making my day a little brighter. :)
 
K

Keith Thompson

Uncle Steve said:
On Thu, May 12, 2011 at 06:53:02PM -0500, Shao Miller wrote: [...]
- Could you employ and enjoy an init() function which would initialize
these objects, then make that the first call inside main()?

No answer to this one? If the very first thing main() does is to call
an init() which populates your globals' values, then that init() makes
for a nicely-readable section of code to gather these items into one place.

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? 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.

The clarity or simplicity of the concept is not the issue.

Yes, the ability to declare a variable outside main() with a
non-constant initializer (say, using a function call) can be
very useful.

But the fact is, standard C doesn't support this feature. If you
need it, you can use a workaround (several have been offered here),
or you can use a non-standard compiler extension if it's available,
or you can use a different language.
 
U

Uncle Steve

On 5/14/2011 1:59 PM, Uncle Steve wrote:
22 PM, Uncle Steve wrote:
[...] I would like to declare:

int foops[] = howmuchfoo(void);

and have everything work as I expect...
[...]

- In your code example, is howmuchfoo() supposed to be returning an
array of 'int' or a single 'int'?

I don't see how that's relevant to the question.

The point is that the one-line fragment you posted is not
valid C, not if `howmuchfoo(void)' is any kind of function at all.

Yes, and I figured out that I had a misconception of how gcc handles
non-constant initilizers. I've already admitted that I'm not coding
anything specific at the moment, and instead /contemplating/ an
approach to solving a particular problem, of which variable
initialization is a part.
(If `howmuchfoo' is a function-like macro, it can of course expand
at compile-time into pretty much anything.) But if it's a function
call, the fragment is meaningless regardless of what scope it appears
in -- which means that by exhibiting it you have conveyed no meaning
to anyone. It is as if you had offered `int foops[] = !<petunia/>;'
and expected people to understand you. If you want to be understood,
you'll have to explain yourself more clearly.
l
I think that I'm being clear enough here.

You think incorrectly. howmuchfoo() can't be a function call. It could

*Now* I know it can't be a function call, but I didn't before. I
thought I explained that already.
be a function-like macro, but if so, the possibilities are too
open-ended to be discussed in the abstract; we need information about
the nature of that macro before your question can be addressed.

No, we need to consider things in the abstract so we may derive
general principles. Is that too much to ask?
It has nothing to do with your sense of humor.

Heh, well that's good.
...

By definition, compiler features mandated by the standard are available
on every single fully conforming implementation. Therefore, code which
relies on any feature that is less than universally prevalent (such as
zero-length arrays) is non-portable.

I was just throwing that out there as an example. I don't really need
zero-length arrays, but if they're available it looks cleaner to use
them.


Regards,

Uncle Steve
 
U

Uncle Steve

Uncle Steve said:
On 5/14/2011 12:59 PM, Uncle Steve wrote:
On Thu, May 12, 2011 at 06:53:02PM -0500, Shao Miller wrote: [...]
- Could you employ and enjoy an init() function which would initialize
these objects, then make that the first call inside main()?


No answer to this one? If the very first thing main() does is to call
an init() which populates your globals' values, then that init() makes
for a nicely-readable section of code to gather these items into one place.

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? 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.

The clarity or simplicity of the concept is not the issue.

Yes, the ability to declare a variable outside main() with a
non-constant initializer (say, using a function call) can be
very useful.

But the fact is, standard C doesn't support this feature. If you
need it, you can use a workaround (several have been offered here),
or you can use a non-standard compiler extension if it's available,
or you can use a different language.

So my question is really answered. Likely, I'll end up calling some
function from main() and merely initialize pointers to NULL in the
global section. No big deal, and thank you all for the suggestions.



Regards,

Uncle Steve
 
S

Shao Miller

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.
 
E

Eric Sosman

[...]
No answer to this one? If the very first thing main() does is to call
an init() which populates your globals' values, then that init() makes
for a nicely-readable section of code to gather these items into one place.

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? [...]

Since it's not C, it's infinitely UNclean in C terms. Also,
you'll find that languages permitting this sort of thing are all
festooned with great garlands of special rules about the order in
which these initializers get executed. Consider your hypothetical
file-scope function call, for example: Are stdin/out/err open and
ready for use when the function runs? What about the `FILE *foo;'
that you also fopen() at file-scope? Has the malloc() arena been
initialized yet? What about floating-point environment flags? And
so on, and so on.
It could do just about anything if it was a C function, couldn't it?

C functions cannot return arrays, nor can they return array
initializers.
 
S

Shao Miller

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?
...
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.
...
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.

As a silly example for why calling a C function to determine the size of
an array at file-scope might be problematic, were it a standard feature:

int compute_some_array_size(void);

char some_array[compute_some_array_size()];

int compute_some_array_size(void) {
if (sizeof some_array == 3)
return 5;
/* Otherwise */
return 3;
}

But perhaps you don't need to have an array at file-scope! You can have
a _pointer_ at file scope and you can malloc() the array using a size
based on the result of calling a C function!

Does that seem reasonable for such empirically-calculated items?
 
U

Uncle Steve

[...]
No answer to this one? If the very first thing main() does is to call
an init() which populates your globals' values, then that init() makes
for a nicely-readable section of code to gather these items into one
place.

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? [...]

Since it's not C, it's infinitely UNclean in C terms. Also,
you'll find that languages permitting this sort of thing are all
festooned with great garlands of special rules about the order in
which these initializers get executed. Consider your hypothetical
file-scope function call, for example: Are stdin/out/err open and
ready for use when the function runs? What about the `FILE *foo;'
that you also fopen() at file-scope? Has the malloc() arena been
initialized yet? What about floating-point environment flags? And
so on, and so on.

I just know I'm going to get into trouble continuing with this. Might
I suggest that it wouldn't be too terrible if the C compiler had
provisions for well-defined user initialization code, happening after
all the libc initialization, etc.? I know it's not in the standard,
but it would be kind of nice to have.
C functions cannot return arrays, nor can they return array
initializers.

Hmm. I'm not sure why you think that's important.



Regards,

Uncle Steve
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
474,095
Messages
2,570,616
Members
47,233
Latest member
GitaQuinte

Latest Threads

Top