Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > C Programming > Handling 'initializer element not constant' error

Reply
Thread Tools

Handling 'initializer element not constant' error

 
 
Gowtham
Guest
Posts: n/a
 
      05-07-2008
Hi,

I had some C code written which initialized a global variable as:

FILE *yyerfp = stdout;

This used to work fine in older versions of gcc. Now, when I tried to
compile this code (with gcc 3.2.3),
I got errors like:

.../Include/Message.h:42: initializer element is not constant

I looked around the www and found that stdin/stdout/stderr are *not*
made const in the newer
versions of gcc.

As a work-around, I thought of this:

FILE *yyerfp; // Uninitialized global

// Initialize it in a separate function
void initializeGlobals( void )
{
yyerfp = stdout;
}

int main( ... )
{
// Initialize the global before doing anything else
initializeGlobals();
...
// Do other things
}

But, this code will also be compiled into a shared object, dynamically
loadable from other
languages such as perl etc. and I do not want to change the API
interface there. If I follow
this approach, I also have to add the initializeGlobals() call in
every perl program which uses
this library.

What is the best way of solving this problem?

Thanks
Gowtham
 
Reply With Quote
 
 
 
 
viza
Guest
Posts: n/a
 
      05-07-2008
Hi

On May 7, 3:14 pm, Gowtham <gowthamgowt...@gmail.com> wrote:

> I had some C code written which initialized a global variable as:
>
> FILE *yyerfp = stdout;
> ...
> But, this code will also be compiled into a shared object
> ...
> What is the best way of solving this problem?


The correct and best way to solve this problem is to remember that
library functions should not write to the standard streams.

Imagine that stdin, stdout and stderr are local variables within
main(). Any library function that needs to write to a file should
take a pointer to one as an argument. The author of main() can then
pass stdout *if* they give you permission to write to it.

This makes your code more modular and easier to reuse, it makes it
easier to read and debug because you can follow information flow from
the prototypes only, and it also stops developers who use your library
from pulling their hair out because you are printing to streams that
you shouldn't, not following their message conventions or corrupting
their output completely.

viza
 
Reply With Quote
 
 
 
 
Willem
Guest
Posts: n/a
 
      05-07-2008
viza wrote:
) Hi
)
) On May 7, 3:14 pm, Gowtham <gowthamgowt...@gmail.com> wrote:
)
)> I had some C code written which initialized a global variable as:
)>
)> FILE *yyerfp = stdout;
)> ...
)> But, this code will also be compiled into a shared object
)> ...
)> What is the best way of solving this problem?
)
) The correct and best way to solve this problem is to remember that
) library functions should not write to the standard streams.
)
) Imagine that stdin, stdout and stderr are local variables within
) main(). Any library function that needs to write to a file should
) take a pointer to one as an argument. The author of main() can then
) pass stdout *if* they give you permission to write to it.
)
) This makes your code more modular and easier to reuse, it makes it
) easier to read and debug because you can follow information flow from
) the prototypes only, and it also stops developers who use your library
) from pulling their hair out because you are printing to streams that
) you shouldn't, not following their message conventions or corrupting
) their output completely.

There was a discussion recently where someone was trying all kinds of hacks
and workarounds to capture the output from a library, because he did not
want it to go to stdout.

I would consider that a very good example of why your advice is good
advice. To the OP: libraries shouldn't be using stdout, and certainly
not hardwired.


SaSW, Willem
--
Disclaimer: I am in no way responsible for any of the statements
made in the above text. For all I know I might be
drugged or something..
No I'm not paranoid. You all think I'm paranoid, don't you !
#EOT
 
Reply With Quote
 
Richard Tobin
Guest
Posts: n/a
 
      05-07-2008
In article <>,
Willem <> wrote:

>)> FILE *yyerfp = stdout;


>I would consider that a very good example of why your advice is good
>advice. To the OP: libraries shouldn't be using stdout, and certainly
>not hardwired.


In general I agree.

But the fact that he's using it to initialise a variable strongly
suggests that it is *not* hardwired, but just a default. If the user
wasn't supposed to be able to change it, the OP could just use stdio
instead of yyerfp.

Assuming the OP can change the code of the library, he could
initialise yyerfp to NULL and replace all the uses of it with

(yyerfp ? yyerfp : stdout)

It's a pity there isn't a standard way to get initialisation code run.

-- Richard
--
:wq
 
Reply With Quote
 
vippstar@gmail.com
Guest
Posts: n/a
 
      05-07-2008
On May 7, 8:01 pm, rich...@cogsci.ed.ac.uk (Richard Tobin) wrote:
> In article <slrng23i52.1aj2.wil...@snail.stack.nl>,
>
> Willem <wil...@stack.nl> wrote:
> >)> FILE *yyerfp = stdout;
> >I would consider that a very good example of why your advice is good
> >advice. To the OP: libraries shouldn't be using stdout, and certainly
> >not hardwired.

>
> In general I agree.
>
> But the fact that he's using it to initialise a variable strongly
> suggests that it is *not* hardwired, but just a default. If the user
> wasn't supposed to be able to change it, the OP could just use stdio
> instead of yyerfp.
>
> Assuming the OP can change the code of the library, he could
> initialise yyerfp to NULL and replace all the uses of it with
>
> (yyerfp ? yyerfp : stdout)

Slightly better way:

FILE *yyerfp_;
/* ... */
#define yyerfp (yyerfp ? yyerfp : stdout)

> It's a pity there isn't a standard way to get initialisation code run.

I don't think it's that much of a problem. Well-designed code wouldn't
use global variables. (with few exceptions such as errno)
 
Reply With Quote
 
vippstar@gmail.com
Guest
Posts: n/a
 
      05-07-2008
On May 7, 8:29 pm, vipps...@gmail.com wrote:
> On May 7, 8:01 pm, rich...@cogsci.ed.ac.uk (Richard Tobin) wrote:
>
> > In article <slrng23i52.1aj2.wil...@snail.stack.nl>,

>
> > Willem <wil...@stack.nl> wrote:
> > >)> FILE *yyerfp = stdout;
> > >I would consider that a very good example of why your advice is good
> > >advice. To the OP: libraries shouldn't be using stdout, and certainly
> > >not hardwired.

>
> > In general I agree.

>
> > But the fact that he's using it to initialise a variable strongly
> > suggests that it is *not* hardwired, but just a default. If the user
> > wasn't supposed to be able to change it, the OP could just use stdio
> > instead of yyerfp.

>
> > Assuming the OP can change the code of the library, he could
> > initialise yyerfp to NULL and replace all the uses of it with

>
> > (yyerfp ? yyerfp : stdout)

>
> Slightly better way:
>
> FILE *yyerfp_;
> /* ... */
> #define yyerfp (yyerfp ? yyerfp : stdout)

Sigh, what's up with all these mistakes lately...
#define yyerfp (yyerfp_ ? yyerfp_ : stdout)

> > It's a pity there isn't a standard way to get initialisation code run.

>
> I don't think it's that much of a problem. Well-designed code wouldn't
> use global variables. (with few exceptions such as errno)


 
Reply With Quote
 
Richard Tobin
Guest
Posts: n/a
 
      05-07-2008
In article <9c2b13d5-b18d-498e-aec8->,
<> wrote:

>> It's a pity there isn't a standard way to get initialisation code run.


>I don't think it's that much of a problem. Well-designed code wouldn't
>use global variables.


You're letting a slogan override your common sense. There are many
cases of global variables that are completely reasonable.

For example, I want to convert between ISO Latin-5 (an 8-bit character
set) and Unicode code points (which can be considered to have 2^16
characters for this purpose). To do this, I have a table of 256
entries mapping Latin-5 to Unicode, and I want to build the reverse
table at start-up. These two global variables, latin_5_to_unicode and
unicode_to_latin_5, have no objectionable properties.

> (with few exceptions such as errno)


Not a reasonable example at all. It was adequate 20 years ago, but
today is a fine example of the problems with global variables.

-- Richard
--
:wq
 
Reply With Quote
 
Keith Thompson
Guest
Posts: n/a
 
      05-07-2008
(Richard Tobin) writes:
> In article <9c2b13d5-b18d-498e-aec8->,
> <> wrote:
>
>>> It's a pity there isn't a standard way to get initialisation code run.

>
>>I don't think it's that much of a problem. Well-designed code wouldn't
>>use global variables.

>
> You're letting a slogan override your common sense. There are many
> cases of global variables that are completely reasonable.
>
> For example, I want to convert between ISO Latin-5 (an 8-bit character
> set) and Unicode code points (which can be considered to have 2^16
> characters for this purpose). To do this, I have a table of 256
> entries mapping Latin-5 to Unicode, and I want to build the reverse
> table at start-up. These two global variables, latin_5_to_unicode and
> unicode_to_latin_5, have no objectionable properties.

[...]

Without resurrecting the unresolved argument over the definition of
"variable" I'll note that your global objects latin_5_to_unicode and
unicode_to_latin_5 presumably do not vary once they've been
initialized. Global objects whose values are never modified during
program execution are less problematic than global objects whose
values can vary over time. ("Global" here refers to file scope and
static duration, more or less.)

--
Keith Thompson (The_Other_Keith) <kst->
Nokia
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"
 
Reply With Quote
 
vippstar@gmail.com
Guest
Posts: n/a
 
      05-07-2008
On May 7, 10:21 pm, rich...@cogsci.ed.ac.uk (Richard Tobin) wrote:
> In article <9c2b13d5-b18d-498e-aec8-d239d0bb3...@25g2000hsx.googlegroups.com>,
>
> <vipps...@gmail.com> wrote:
> >> It's a pity there isn't a standard way to get initialisation code run.

> >I don't think it's that much of a problem. Well-designed code wouldn't
> >use global variables.

>
> You're letting a slogan override your common sense. There are many
> cases of global variables that are completely reasonable.
>
> For example, I want to convert between ISO Latin-5 (an 8-bit character
> set) and Unicode code points (which can be considered to have 2^16
> characters for this purpose). To do this, I have a table of 256
> entries mapping Latin-5 to Unicode, and I want to build the reverse
> table at start-up. These two global variables, latin_5_to_unicode and
> unicode_to_latin_5, have no objectionable properties.

Ah, indeed. Another example would be a table for all the is*()
functions in <ctype.h>, in a C lib implementation.
I just try to avoid global variables, because they can lead to a bad
design, when there's a better option available.
> > (with few exceptions such as errno)

>
> Not a reasonable example at all. It was adequate 20 years ago, but
> today is a fine example of the problems with global variables.

OK, you are right. I can see what you mean, one example would be with
threads I suppose.
I have not read much on alternative solutions to errno in C, so is
there a better solution?
Returning the error code is not possible (like pthreads) and an extra
parameter to every function that can fail would be quite annoying.
 
Reply With Quote
 
Peter Nilsson
Guest
Posts: n/a
 
      05-07-2008
Gowtham wrote:
> Hi,
>
> I had some C code written which initialized a global variable as:
>
> FILE *yyerfp = stdout;


In C, stdin, stdout and stderr are macros. They needn't be
constant expressions.

> This used to work fine in older versions of gcc. Now, when I
> tried to compile this code (with gcc 3.2.3),
> I got errors like:
>
> ../Include/Message.h:42: initializer element is not constant


That is your error, not glibc's.

> I looked around the www and found that stdin/stdout/stderr
> are *not* made const in the newer versions of gcc.


They don't need to be.

> As a work-around, I thought of this:
>
> FILE *yyerfp; // Uninitialized global


Actually, it's zero initialised (to a null pointer).

> // Initialize it in a separate function
> void initializeGlobals( void )
> {
> yyerfp = stdout;
> }
>
> int main( ... )
> {
> // Initialize the global before doing anything else
> initializeGlobals();
> ...
> // Do other things
> }
>
> But, this code will also be compiled into a shared object,
> dynamically loadable from other languages such as perl etc.
> and I do not want to change the API interface there.


Fine, but in a sense, it's your interface that is a problem.

> If I follow this approach, I also have to add the
> initializeGlobals() call in every perl program which uses
> this library.


Replace it with a macro/function like...

#define YYERFP \
(yyerfp ? yyerfp : (yyerfp = stdout))

int library_foo()
{
FILE *fp = YYERFP;
...
}

<OT> The other choice of course is C++ </OT>

> What is the best way of solving this problem?


Don't make libraries dependant on non-zero initialisation of
static variables.

--
Peter
 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
Element 'ElephantTreeView' is not a known element. This can occur ifthere is a compilation error in the Web site, or the web.config file ismissing. Options Dave ASP .Net 0 07-05-2010 03:54 PM
Handling DOM event on element not on top Daniel Kraft Javascript 0 09-27-2008 02:26 PM
Element is not a known element. This can occur if there is a compilation error in the Web site MK ASP .Net 5 06-27-2008 07:20 PM
how to Update/insert an xml element's text----> (<element>text</element>) HANM XML 2 01-29-2008 03:31 PM
Solution: "Element '%' is not a known element. This can occur if there is a compilation error in the Web site" hirebrian@hotmail.com ASP .Net 0 08-14-2007 12:51 AM



Advertisments
 



1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57