Non-constant initializers

  • Thread starter Fred the Freshwater Catfish
  • Start date
F

Fred the Freshwater Catfish

Hey guys,

I've been writing some code that I would prefer to be maximally
portable. As I have mostly used Linux, gcc is pretty much the only C
compiler I've ever used under UN*X. I'd like to use non-constant
initializers for some global variables. I'm pretty sure I can get it
to work the way I want under gcc, but what of other compilers? The
gcc documentation in info format says that ISO C99 allows this, and so
I expect some compilers built in the 90's will support the feature,
but to what extent is this true?

What I mean to learn is the general prevalence of this C feature. If
there's no support for certain well-known platforms (maybe SunOS or
OSF/1, whatever) I may consider a different solution to the original
problem, but I'd like to know what I'm getting in to before I start
trying to read the docs for every bloody C compiler that ever hit the
'net in the last twenty years.

Thanks if you can shed any light on this subject.



Fred the Freshwater Catfish
 
I

Ian Collins

Hey guys,

I've been writing some code that I would prefer to be maximally
portable. As I have mostly used Linux, gcc is pretty much the only C
compiler I've ever used under UN*X. I'd like to use non-constant
initializers for some global variables. I'm pretty sure I can get it
to work the way I want under gcc, but what of other compilers? The
gcc documentation in info format says that ISO C99 allows this, and so
I expect some compilers built in the 90's will support the feature,
but to what extent is this true?

How do you derive the initialiser values?
 
S

Shao Miller

...I'd like to use non-constant
initializers for some global variables. I'm pretty sure I can get it
to work the way I want under gcc, but what of other compilers? The
gcc documentation in info format says that ISO C99 allows this, and so
I expect some compilers built in the 90's will support the feature,
but to what extent is this true?

Could you please share an example of what kind of non-constant you'd be
inclined to initialize a static-duration, file-scoped object with? Are
you talking about using a function's return value? Are you talking
about using the address of something whose address you don't know at
some point in time?
 
U

Uncle Steve

Could you please share an example of what kind of non-constant you'd be
inclined to initialize a static-duration, file-scoped object with? Are
you talking about using a function's return value? Are you talking
about using the address of something whose address you don't know at
some point in time?

Essentially, 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. Pie in the sky for non-recent
UN*Xes?



Regards,

Uncle Steve
 
F

Fred the Freshwater Catfish

I use an alternative strategy: if I want to implement
static double XYZ = nonconstant-expression;

I instead do
#define XYZ (*XYZ_())
static double *XYZ_(void) {
static double xyz;
static bool initialised = false;
LOCK
if (!initialised) {
xyz = nonconstant-expression;
initialised = true;
}
UNLOCK
return &xyz;
}

XYZ will be an lvalue just like any other variable; it gets initialised on the
first use; the initialisation can be any complicated as desired, using any
dependencies desired, without depending on the compiler and loader to sneak in
the initialisation code in the right order.

Hey, is that how you ancients did things in the 80's era? I hope
there's a better way.



Fred the Freshwater Catfish
 
I

Ian Collins

Sorry, I'm not using C++.

But you require a C++ feature...

You could compile all but main() as C and compile the source file
containing main() and your initialisers as C++.
 
K

Keith Thompson

Ian Collins said:
But you require a C++ feature...

You could compile all but main() as C and compile the source file
containing main() and your initialisers as C++.

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

Shao Miller

Essentially,

Are you the same person as "Fred the Freshwater Catfish"? Or are you
another person who also wishes to accomplish this type of thing?
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()?

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

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

- Would you be willing to use macros to accomplish this?
 
J

Joe Pfeiffer

Fred the Freshwater Catfish said:
I've been writing some code that I would prefer to be maximally
portable. As I have mostly used Linux, gcc is pretty much the only C
compiler I've ever used under UN*X. I'd like to use non-constant
initializers for some global variables. I'm pretty sure I can get it
to work the way I want under gcc, but what of other compilers? The
gcc documentation in info format says that ISO C99 allows this, and so
I expect some compilers built in the 90's will support the feature,
but to what extent is this true?

Where does the documentation say this is allowed by C99? The C99
standard says

All the expressions in an initializer for an object that has static
storage duration shall be constant expressions or string literals.

(Section 6.7.8 paragraph 4)
 
S

Seebs

Essentially, 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. Pie in the sky for non-recent
UN*Xes?

IMHO, incoherent. When, EXACTLY, do you want "howmuchfoo()" to run?
Do you anticipate that main() will have been called yet? Do you expect
the C library to be available?

The reason the singleton hack exists is that what you want here is something
that's only meaningfully specified in C++.

-s
 
K

Keith Thompson

Joe Pfeiffer said:
Where does the documentation say this is allowed by C99? The C99
standard says

All the expressions in an initializer for an object that has static
storage duration shall be constant expressions or string literals.

(Section 6.7.8 paragraph 4)

I think this is the relevant section of the gcc document:

6.23 Non-Constant Initializers
==============================

As in standard C++ and ISO C99, the elements of an aggregate
initializer for an automatic variable are not required to
be constant expressions in GNU C. Here is an example of an
initializer with run-time varying elements:

foo (float f, float g)
{
float beat_freqs[2] = { f-g, f+g };
/* ... */
}

C90 requires constant expression for all initializers. C99 permits
non-constant expressions, but only for automatic variables.
 
J

Joe Pfeiffer

Keith Thompson said:
Joe Pfeiffer said:
Where does the documentation say this is allowed by C99? The C99
standard says

All the expressions in an initializer for an object that has static
storage duration shall be constant expressions or string literals.

(Section 6.7.8 paragraph 4)

I think this is the relevant section of the gcc document:

6.23 Non-Constant Initializers
==============================

As in standard C++ and ISO C99, the elements of an aggregate
initializer for an automatic variable are not required to
be constant expressions in GNU C. Here is an example of an
initializer with run-time varying elements:

foo (float f, float g)
{
float beat_freqs[2] = { f-g, f+g };
/* ... */
}

C90 requires constant expression for all initializers. C99 permits
non-constant expressions, but only for automatic variables.

The OP said he wanted non-constant initializers for global variables,
not for automatic variables.
 
S

Seebs

(Followups to comp.lang.c only, this has nothing to do with comp.arch.)

The OP said he wanted non-constant initializers for global variables,
not for automatic variables.

Yes. But the question was where in the gcc docs there was anything about
C99 allowing non-constant initializers. The answer is, there. Only, as
you note, it doesn't say it about globals.

-s
 
J

Joe Pfeiffer

Seebs said:
(Followups to comp.lang.c only, this has nothing to do with comp.arch.)




Yes. But the question was where in the gcc docs there was anything about
C99 allowing non-constant initializers. The answer is, there. Only, as
you note, it doesn't say it about globals.

As the guy who asked the question ("where in the GCC docs?"), I did
indeed mean non-constant initializers for globals when I said "this".
To restore the relevant context you deleted:
 
S

Seebs

As the guy who asked the question ("where in the GCC docs?"), I did
indeed mean non-constant initializers for globals when I said "this".

Yeah. I think that the rationale of the response was roughly:
* Obviously, it doesn't
* But there is a section of the docs which refers to C99 and
to non-constant initializers
* Presenting that could explain where the confusion came from
that led someone to think that gcc's docs said that C99
allowed this

-s
 
F

Fred the Freshwater Catfish

Where does the documentation say this is allowed by C99? The C99
standard says

All the expressions in an initializer for an object that has static
storage duration shall be constant expressions or string literals.

(Section 6.7.8 paragraph 4)

I figured out my problem. First, the docs:

File: gcc-4.5.info, Node: Initializers, Next: Compound Literals, Prev:
Pointer Arith, Up: C Extensions

6.23 Non-Constant Initializers
==============================

As in standard C++ and ISO C99, the elements of an aggregate
initializer for an automatic variable are not required to be constant
expressions in GNU C. Here is an example of an initializer with
run-time varying elements:

foo (float f, float g)
{
float beat_freqs[2] = { f-g, f+g };
/* ... */
}



1 #include <stdio.h>
2 #include <fcntl.h>
3 #include <stdlib.h>

5 int * initialize(void)
6 {
7 int *p;
8 int fd;
9
10 fd = open("/dev/urandom", O_RDONLY);
11 if(-1 == fd) {
12 perror("open()");
13 exit(1);
14 }
15
16 read(fd, p, sizeof(int *));
17
18 return(p);
19 }
20
21 main(int argc, char ** argv)
22 {
23 int * glob = initialize();
24
25 fprintf(stdout, "glob = %d\n", glob);
26
27 exit(0);
28 }

So I thought I could move the "glob = initialize()" call out of main()
and have a convenient way to set up global variables. This is the
problem of designing vaporware when there are a lot of details to
manage. I'll just have to arrange to load/save my globals with a
little bit more work. Anyhow, my initial question was related to
efforts to avoid using compilerisms which might lead to portability
issues. As my project approaches alpha-release material, I'm trying
to plan ahead enough to avoid massive rewrites in stuff that could
limit portability.

Sorry for my misinterpretation of gcc capabilities.



Fred the Freshwater Catfish
 
F

Fred the Freshwater Catfish

But you require a C++ feature...

You could compile all but main() as C and compile the source file
containing main() and your initialisers as C++.

I guess, but then my code would be tainted by C++. I'd rather avoid
requiring C++ in the build toolchain to compile the software.


Fred the Freshwater Catfish
 

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
473,743
Messages
2,569,478
Members
44,899
Latest member
RodneyMcAu

Latest Threads

Top