initializer element is not constant

P

Paul Edwards

On ecgs (gcc) 2.91.57 and on gcc 3.2.3 I am getting the
error "initializer element is not constant" on the below
code. The code compiles fine with other compilers I
have. Is this valid C89 code?

extern int *b;

int *a = b;

int main(void)
{
return (0);
}

Thanks. Paul.
 
P

Paul Edwards

Sorry folks, the code fails on my other compilers too.

It was this code:

#include <stdio.h>

FILE *a = stderr;

int main(void)
{
return (0);
}

that only failed on gcc. And given that it also fails on ints, I
guess gcc is behaving correctly.

BFN. Paul.
 
J

Jack Klein

On ecgs (gcc) 2.91.57 and on gcc 3.2.3 I am getting the
error "initializer element is not constant" on the below
code. The code compiles fine with other compilers I
have. Is this valid C89 code?

No, it is not. Initializers for objects with static storage duration,
and that includes all objects defined at file scope, must be constant
expressions. You are trying to initialize the pointer 'a' with the
value of another object. The value of any object, even if it is a
const qualified object, is not a constant expression in C.
extern int *b;

int *a = b;

int main(void)
{
return (0);
}

Even this is not (necessarily) valid C:

int x;
int *const b = &x; /* valid, &x is an address constant */
int *a = b; /* not valid */

The initialization of 'a' is not valid even though the value of 'b' is
known at compile time, which it is not in your case. The value of an
object is just not among the defined constant expressions in the C
standard.

It is actually possible for a compiler to accept this as an extension,
that being the reason for the (necessarily) I wrote above, because the
C standard allows an implementation to "accept other forms of constant
expressions". But I don't know of any implementation that does.
 
J

Jack Klein

Sorry folks, the code fails on my other compilers too.

It was this code:

#include <stdio.h>

FILE *a = stderr;

int main(void)
{
return (0);
}

that only failed on gcc. And given that it also fails on ints, I
guess gcc is behaving correctly.

This one is a different story. It works on some compilers and fails
on others. It depends on the compiler's definition of the macro
"stderr". The C standard requires that stdin, stdout, and stderr are
macros that expand to pointers to file, and depending on how the
macros are defined, they may or may not be address constants at
compile time.

So you should not use this, because as you found out it may work on
some implementations but not others.

The easy fix is to leave the pointer uninitialized, which means it
gets default initialized to NULL, and in main(), before it is used,
assign it.
 
P

Paul Edwards

Jack Klein said:
This one is a different story. It works on some compilers and fails
on others. It depends on the compiler's definition of the macro
"stderr". The C standard requires that stdin, stdout, and stderr are
macros that expand to pointers to file, and depending on how the
macros are defined, they may or may not be address constants at
compile time.

Hi Jack, thanks for your reply. The C90 standard says that
stdin, stdout and stderr are "expressions of type "pointer to
FILE" that point to FILE objects...". It doesn't say they are
macros.
So you should not use this, because as you found out it may work on
some implementations but not others.

I found out how the working version was implemented and
duplicated it, and it works on gcc as well.

#include <stdio.h>

extern FILE myfiles[];

FILE *a = &myfiles[0];

int main(void)
{
return (0);
}

I see what you mean - it is an address here, rather than a
variable.
The easy fix is to leave the pointer uninitialized, which means it
gets default initialized to NULL, and in main(), before it is used,
assign it.

Yes, I have basically done this now. I'm porting bwbasic
to MVS 3.8.

BFN. Paul.
 
P

pete

Paul said:
The C90 standard says that stdin, stdout and stderr are
"expressions of type "pointer to FILE"
that point to FILE objects...".
It doesn't say they are macros.

The first three words of the sentence that you are quoting
from 7.9.1 are: "The macros are ..."
 
K

Keith Thompson

pete said:
The first three words of the sentence that you are quoting
from 7.9.1 are: "The macros are ..."

And that's a truly impressive run-on sentence (it starts more than a
page earlier).

The wording does cause some confusion. For all the other macros in
that sentence, the standard uses the phrase "which expands to" or
"which expand to"; for stderr, stdin, and stdout, is says "which are
expression ...".

I raised this a few months ago in comp.std.c:

http://groups.google.com/group/comp.std.c/browse_frm/thread/724f1ef38d3e8250/5254094bb4950930

The consensus was that std{err,in,out} *are* required to be macros.
(The restriction isn't necessarily useful, but there's no point in
allowing the trivial extra flexibility for implementers.)
 

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

No members online now.

Forum statistics

Threads
473,768
Messages
2,569,575
Members
45,053
Latest member
billing-software

Latest Threads

Top