C89: Compile-time constant required for initialiser?

  • Thread starter Tomás Ó hÉilidhe
  • Start date
T

Tomás Ó hÉilidhe

I've been developing a C89 microcontroller application for a while
now and I've been testing its compilation using gcc. I've gotten zero
errors and zero warnings with gcc, but now that I've moved over to the
micrcontroller compiler I'm getting all sorts of errors.

One thing I'd like to clarify is the need (in C89) for a compile-
time constant in the initialiser of a variable. The compiler rejects the
following source file:

/* Start foo.c */

int const a = 7;

int b = a;

/* End foo.c */


It says that the initialiser of "b" needs to be a compile-time
constant. Is it true that the initialiser of a non-const global object
needs to be a compile-time constant in C89? Or is this just a short
coming of the compiler?

Another related question:

/* Start bar.c */

void Func(void)
{
int const x = 7;

int const y = x;
}

/* End bar.c

In the snippet immediately above, the compiler fails because y's
initialiser isn't a compile-time constant. How does C89 view this? (If
"y" is made non-const, then the compiler accepts the code, but I'm
wondering if a _const_ local automatic variable's initialiser must be a
compile-time constant in C89?)
 
P

pete

Tomás Ó hÉilidhe said:
I've been developing a C89 microcontroller application for a while
now and I've been testing its compilation using gcc. I've gotten zero
errors and zero warnings with gcc, but now that I've moved over to the
micrcontroller compiler I'm getting all sorts of errors.

One thing I'd like to clarify is the need (in C89) for a compile-
time constant in the initialiser of a variable.
The compiler rejects the following source file:

/* Start foo.c */

int const a = 7;

int b = a;

/* End foo.c */

It says that the initialiser of "b" needs to be a compile-time
constant. Is it true that the initialiser of a non-const global object
needs to be a compile-time constant in C89?

Yes.
Here's the relevant concept:
global objects have static duration and therefore
are initialized before main starts executing.
Or is this just a short
coming of the compiler?

No.
Another related question:

/* Start bar.c */

void Func(void)
{
int const x = 7;

int const y = x;
}

/* End bar.c

In the snippet immediately above, the compiler fails because y's
initialiser isn't a compile-time constant. How does C89 view this?

It shouldn't be that way.
Func is useless, but flawless.
(If "y" is made non-const, then the compiler accepts the code,
but I'm wondering if a _const_ local automatic
variable's initialiser must be a compile-time constant in C89?)

No. Absolutely not.

char *str_cpy(char *s1, const char *s2)
{
char *const p1 = s1;

while ((*s1++ = *s2++) != '\0') {
;
}
return p1;
}
 
T

Thad Smith

Tomás Ó hÉilidhe said:
One thing I'd like to clarify is the need (in C89) for a compile-
time constant in the initialiser of a variable. The compiler rejects the
following source file:

/* Start foo.c */

int const a = 7;
int b = a;

/* End foo.c */

It says that the initialiser of "b" needs to be a compile-time
constant. Is it true that the initialiser of a non-const global object
needs to be a compile-time constant in C89?

Yes. The same is true of C99. The declaration of a, above, has a
different meaning in C than C++.
Or is this just a short coming of the compiler?
No.

Another related question:

/* Start bar.c */
void Func(void)
{
int const x = 7;
int const y = x;
}
/* End bar.c

In the snippet immediately above, the compiler fails because y's
initialiser isn't a compile-time constant. How does C89 view this?

That is a valid initialization, assuming that y is not declared static.
(If "y" is made non-const, then the compiler accepts the code, but I'm
wondering if a _const_ local automatic variable's initialiser must be a
compile-time constant in C89?)

That looks like a compiler bug to me.
 
B

Ben Pfaff

Tomás Ó hÉilidhe said:
I've been developing a C89 microcontroller application for a while
now and I've been testing its compilation using gcc. I've gotten zero
errors and zero warnings with gcc, but now that I've moved over to the
micrcontroller compiler I'm getting all sorts of errors. ....
Is it true that the initialiser of a non-const global object
needs to be a compile-time constant in C89?

Yes. (GCC complains about this too. Are you sure that you
didn't compile your program as C++? C++ allows this.)

....
void Func(void)
{
int const x = 7;

int const y = x;
} ....
In the snippet immediately above, the compiler fails because y's
initialiser isn't a compile-time constant. How does C89 view this?

This code is fine.
(If "y" is made non-const, then the compiler accepts the code,
but I'm wondering if a _const_ local automatic variable's
initialiser must be a compile-time constant in C89?)

No, it need not be.
 
T

Tomás Ó hÉilidhe

That is a valid initialization, assuming that y is not declared
static.


Is that to say that static variables within functions get exactly the same
treatment as global variables when it comes to initialisation? That is to
say, should I C89 compiler reject the following?:


void Func(void)
{
static int a = (0,2);
}

(I use the comma operator so as not to yield a compile-time constant).
 
P

pete

Tomás Ó hÉilidhe wrote:
Is that to say that static variables within
functions get exactly the same
treatment as global variables when it comes to initialisation?

Yes.
Here's the relevant concept:
static variables within functions and global objects,
have static duration and therefore
are initialized before main starts executing.
 
P

pete

pete said:
Yes.
Here's the relevant concept:
static variables within functions and global objects,
have static duration and therefore
are initialized before main starts executing.

Though,
the relevant concept doesn't explain what's wrong with (0,2),
so I'll stop repeating it.
 
T

Tomás Ó hÉilidhe

pete said:
Though,
the relevant concept doesn't explain what's wrong with (0,2),
so I'll stop repeating it.


What's wrong with (0,2)? It evaluates to an R-value whose type is int and
whose value is 2. Fair enough it's not a compile-time constant... but what
exactly are you saying is wrong with it?
 
P

pete

Tomás Ó hÉilidhe said:
What's wrong with (0,2)?
It evaluates to an R-value whose type is int and whose value is 2.
Fair enough it's not a compile-time constant...
but what exactly are you saying is wrong with it?

It's not a "constant expression".
What I was getting at,
was that since objects with static duration
are initialised before main starts executing,
they need to be initialised with compile time constants.
However, the value of (0,2) is capable of being evaluated
at a glance, even before compile time,
and the only reason that it is not considered a
constant expression is because of the rules banning comma
operators from evaluated parts of constant expressions.

The problem is that there is no such term as
"compile-time constant" in the standard.
Where a "compile-time constant" is needed,
a "constant expression" is called for.

ISO/IEC 9899: 1990
6.5.7 Initialization
All the expressions in an initializer for an object that has static
storage duration or in an initializer list for an object that has
aggregate or union type shall be constant expressions.

But I think you knew that already.
 
F

Flash Gordon

Tomás Ó hÉilidhe wrote, On 09/12/07 22:14:
I've been developing a C89 microcontroller application for a while
now and I've been testing its compilation using gcc. I've gotten zero
errors and zero warnings with gcc, but now that I've moved over to the
micrcontroller compiler I'm getting all sorts of errors.

<snip>

Something that others have not mentioned which may help you is that by
default gcc permits all sorts of extensions some of which are
incompatible with the C standard. To get it to follow the standard you
should use "gcc -ansi -pedantic" to get a lot more useful warnings try
"gcc -ansi -pedantic -Wall -Wextra".
 
T

Tomás Ó hÉilidhe

Something that others have not mentioned which may help you is that by
default gcc permits all sorts of extensions some of which are
incompatible with the C standard. To get it to follow the standard you
should use "gcc -ansi -pedantic" to get a lot more useful warnings try
"gcc -ansi -pedantic -Wall -Wextra".


I actually posted to gnu.gcc.help to ask them what compiler options I
should use for smart C89 programming, but I didn't get a response.

I've tried using -Wall, but stupidly it gives be warnings about stuff in
the standard header files (e.g. usage of #includenext in stdio.h).
 
C

CBFalconer

Tomás Ó hÉilidhe said:
I actually posted to gnu.gcc.help to ask them what compiler
options I should use for smart C89 programming, but I didn't get
a response.

I've tried using -Wall, but stupidly it gives be warnings about
stuff in the standard header files (e.g. usage of #includenext
in stdio.h).

I believe you have a misinstallation. There is no such usage in
stdio.h for gcc.
 
K

Keith Thompson

CBFalconer said:
I believe you have a misinstallation. There is no such usage in
stdio.h for gcc.

Of course there isn't. There is no stdio.h in gcc. stdio.h is
provided along with the runtime library, which is a separate component
from gcc, which is just a compiler.
 
C

CBFalconer

Keith said:
Of course there isn't. There is no stdio.h in gcc. stdio.h is
provided along with the runtime library, which is a separate
component from gcc, which is just a compiler.

This is a disgusting reply, which ignores the OPs problem. To all
practical purposess, no installation of gcc is complete without a
matching stdio.h.
 
K

Keith Thompson

CBFalconer said:
This is a disgusting reply, which ignores the OPs problem. To all
practical purposess, no installation of gcc is complete without a
matching stdio.h.

"Disgusting"??? Chuck, what is your problem?

My point is simply that the <stdio.h> header is provided by the
runtime library, *not* by gcc. Yes, gcc needs to be combined with a
runtime library before it can be used as a C implementation, but it
can be used with a number of different runtime libraries. On Linux
systems, it's commonly used with glibc; on Solaris, it's used with
Sun's runtime library; on other systems, it uses whatever library
happens to be available.

I was not attempting to address the OP's problem, because I don't know
the solution (I'd suggest posting to gnu.gcc.help, but he said he'd
already tried that). I was merely correcting your misstatement, that
"There is no such usage in stdio.h for gcc".

<OT>A bit of research shows that "#include_next", not "#includenext",
is a gcc extension. Perhaps the OP is using a stdio.h that's designed
to be used with gcc, but that isn't designed properly to be used with
"gcc -Wall". On one system I use (Ubuntu), the only header that uses
"#include_next" is limits.h. Perhaps the OP is using an older
system.</OT>
 
R

Richard Tobin

Of course there isn't. There is no stdio.h in gcc. stdio.h is
provided along with the runtime library, which is a separate
component from gcc, which is just a compiler.
[/QUOTE]
This is a disgusting reply, which ignores the OPs problem. To all
practical purposess, no installation of gcc is complete without a
matching stdio.h.

But the stdio.h mainly has to match the system, not gcc. Gcc uses
dozens of different stdio.h files on different platforms. The problem
must be specific to some particular gcc/platform combination, such as
gcc + glibc for Linux.

-- Richard
 
T

Tomás Ó hÉilidhe

<OT>A bit of research shows that "#include_next", not "#includenext",
is a gcc extension. Perhaps the OP is using a stdio.h that's designed
to be used with gcc, but that isn't designed properly to be used with
"gcc -Wall".


It would be great if there was a commandline option for ignoring warnings
in certain files, e.g.:

gcc -ansi -pedantic -Wall -Wingore
limits.h,ctype.h,math.h,stdio.h,stdlib.h,blah blah

But of course it's ridiculous that compiler would give warnings from files
in the standard library.

Could someone please give me a sample of what command line options they use
for gcc? At the moment I've got:

gcc -std=c89 -pedantic -Wall -Werror-implicit-int -Werror-implicit-
function-declaration

(not copy-pasted verbatim so I may have miswritten one of them)
 
R

Richard Heathfield

Tomás Ó hÉilidhe said:

But of course it's ridiculous that compiler would give warnings from
files in the standard library.

GNU isn't alone - my Visual C implementation diagnoses math.h - and if I
set the warning level up to max and try to compile the Win32 headers
(which, admittedly, are not part of the standard library), it goes
completely bananas.
Could someone please give me a sample of what command line options they
use for gcc? At the moment I've got:

gcc -std=c89 -pedantic -Wall -Werror-implicit-int -Werror-implicit-
function-declaration

I use: -W -Wall -ansi -pedantic -Wformat-nonliteral -Wcast-align
-Wpointer-arith -Wbad-function-cast -Wmissing-prototypes
-Wstrict-prototypes -Wmissing-declarations -Winline -Wundef
-Wnested-externs -Wcast-qual -Wshadow -Wconversion -Wwrite-strings
-ffloat-store -O2

and I add -g and -pg when necessary.
 
K

Keith Thompson

Tomás Ó hÉilidhe said:
But of course it's ridiculous that compiler would give warnings from files
in the standard library.
[...]

Not necessarily. Just because a file is part of an implementation of
the standard library doesn't mean that it's immune from errors.

I agree that it would be nice to have an option to suppress warnings
about files you don't have any control over. But a better solution is
probably for the authors of the implementation to fix their headers so
they don't trigger warnings.
 
T

Tomás Ó hÉilidhe

Not necessarily. Just because a file is part of an implementation of
the standard library doesn't mean that it's immune from errors.



If I am *not* to assume that the implementation's standard library is free
from errors, then I may as well drop a boat-load of other assumptions that
I make in life, such as whether something will fall downward or upwards if
I let go of it, or whether my right arm will move if I will it to move.


I agree that it would be nice to have an option to suppress warnings
about files you don't have any control over. But a better solution is
probably for the authors of the implementation to fix their headers so
they don't trigger warnings.


If a particular implementor wants to use #include_green_lava in its header
files then let it... I just don't want to get errors or warnings about code
which is:

a) Not mine
b) Assumed to be perfect by the code which calls it
 

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,769
Messages
2,569,577
Members
45,054
Latest member
LucyCarper

Latest Threads

Top