Handling 'initializer element not constant' error

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • Gowtham

    #1

    Handling 'initializer element not constant' error

    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 initializeGloba ls( void )
    {
    yyerfp = stdout;
    }

    int main( ... )
    {
    // Initialize the global before doing anything else
    initializeGloba ls();
    ...
    // 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 initializeGloba ls() call in
    every perl program which uses
    this library.

    What is the best way of solving this problem?

    Thanks
    Gowtham
  • viza

    #2
    Re: Handling 'initializer element not constant' error

    Hi

    On May 7, 3:14 pm, Gowtham <gowthamgowt... @gmail.comwrote :
    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

    Comment

    • Willem

      #3
      Re: Handling 'initializer element not constant' error

      viza wrote:
      ) Hi
      )
      ) On May 7, 3:14 pm, Gowtham <gowthamgowt... @gmail.comwrote :
      )
      )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

      Comment

      • Richard Tobin

        #4
        Re: Handling 'initializer element not constant' error

        In article <slrng23i52.1aj 2.willem@snail. stack.nl>,
        Willem <willem@stack.n lwrote:
        >)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

        Comment

        • vippstar@gmail.com

          #5
          Re: Handling 'initializer element not constant' error

          On May 7, 8:01 pm, rich...@cogsci. ed.ac.uk (Richard Tobin) wrote:
          In article <slrng23i52.1aj 2.wil...@snail. stack.nl>,
          >
          Willem <wil...@stack.n lwrote:
          )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)

          Comment

          • vippstar@gmail.com

            #6
            Re: Handling 'initializer element not constant' error

            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.1aj 2.wil...@snail. stack.nl>,
            >
            Willem <wil...@stack.n lwrote:
            >)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)

            Comment

            • Richard Tobin

              #7
              Re: Handling 'initializer element not constant' error

              In article <9c2b13d5-b18d-498e-aec8-d239d0bb3a23@25 g2000hsx.google groups.com>,
              <vippstar@gmail .comwrote:
              >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_unic ode and
              unicode_to_lati n_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

              Comment

              • Keith Thompson

                #8
                Re: Handling 'initializer element not constant' error

                richard@cogsci. ed.ac.uk (Richard Tobin) writes:
                In article <9c2b13d5-b18d-498e-aec8-d239d0bb3a23@25 g2000hsx.google groups.com>,
                <vippstar@gmail .comwrote:
                >
                >>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_unic ode and
                unicode_to_lati n_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_unic ode and
                unicode_to_lati n_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_Keit h) <kst-u@mib.org>
                Nokia
                "We must do something. This is something. Therefore, we must do this."
                -- Antony Jay and Jonathan Lynn, "Yes Minister"

                Comment

                • vippstar@gmail.com

                  #9
                  Re: Handling 'initializer element not constant' error

                  On May 7, 10:21 pm, rich...@cogsci. ed.ac.uk (Richard Tobin) wrote:
                  In article <9c2b13d5-b18d-498e-aec8-d239d0bb3...@25 g2000hsx.google groups.com>,
                  >
                  <vipps...@gmail .comwrote:
                  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_unic ode and
                  unicode_to_lati n_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.

                  Comment

                  • Peter Nilsson

                    #10
                    Re: Handling 'initializer element not constant' error

                    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 initializeGloba ls( void )
                    {
                    yyerfp = stdout;
                    }
                    >
                    int main( ... )
                    {
                    // Initialize the global before doing anything else
                    initializeGloba ls();
                    ...
                    // 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
                    initializeGloba ls() 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;
                    ...
                    }

                    <OTThe 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

                    Comment

                    • Richard Tobin

                      #11
                      Re: Handling 'initializer element not constant' error

                      In article <290288be-6c58-49e1-9bef-ec4e3e5de7ca@l4 2g2000hsc.googl egroups.com>,
                      <vippstar@gmail .comwrote:
                      >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.
                      The C standard recognises the problems with errno and doesn't require
                      it to be an identifier. It just has to be a macro that produces a
                      modifiable lvalue. So a threaded implementation can do something
                      like

                      #define errno (*__thread_errn o())

                      where __thread_errno( ) returns a pointer to a per-thread variable.

                      -- Richard
                      --
                      :wq

                      Comment

                      • Ben Pfaff

                        #12
                        Re: Handling 'initializer element not constant' error

                        richard@cogsci. ed.ac.uk (Richard Tobin) writes:
                        The C standard recognises the problems with errno and doesn't require
                        it to be an identifier.
                        It's definitely an identifier. However, it might not be the name
                        of a variable with external linkage.
                        --
                        "I hope, some day, to learn to read.
                        It seems to be even harder than writing."
                        --Richard Heathfield

                        Comment

                        • Richard Tobin

                          #13
                          Re: Handling 'initializer element not constant' error

                          In article <87abj1u4q4.fsf @blp.benpfaff.o rg>,
                          Ben Pfaff <blp@cs.stanfor d.eduwrote:
                          >The C standard recognises the problems with errno and doesn't require
                          >it to be an identifier.
                          >It's definitely an identifier.
                          Obviously "errno" is an identifier. I should have said that it's a
                          macro that doesn't have to expand to an identifier.
                          >However, it might not be the name of a variable with external linkage.
                          It might not expand to the name of a variable at all.

                          -- Richard
                          --
                          :wq

                          Comment

                          • dj3vande@csclub.uwaterloo.ca.invalid

                            #14
                            Re: Handling 'initializer element not constant' error

                            In article <87abj1u4q4.fsf @blp.benpfaff.o rg>,
                            Ben Pfaff <blp@cs.stanfor d.eduwrote:
                            >richard@cogsci .ed.ac.uk (Richard Tobin) writes:
                            >
                            >The C standard recognises the problems with errno and doesn't require
                            >it to be an identifier.
                            >
                            >It's definitely an identifier. However, it might not be the name
                            >of a variable with external linkage.
                            errno is explicitly allowed to be a macro (n869 7.5#2).
                            A brief look through the definitions in n869 indicates that a macro
                            name is indeed covered under the standardese use of "identifier ", but
                            it seems that referring to a macro as an identifier in informal use is
                            gratuitiously confusing, especially when what the macro expands to need
                            not be an identifier.


                            dave

                            --
                            Dave Vandervies dj3vande at eskimo dot com
                            I would definitely not be sure that it does what the programmer
                            intended, even if the programmer was me.
                            --Christian Bau in comp.lang.c

                            Comment

                            • Ben Pfaff

                              #15
                              Re: Handling 'initializer element not constant' error

                              richard@cogsci. ed.ac.uk (Richard Tobin) writes:
                              In article <87abj1u4q4.fsf @blp.benpfaff.o rg>,
                              Ben Pfaff <blp@cs.stanfor d.eduwrote:
                              >
                              >>The C standard recognises the problems with errno and doesn't require
                              >>it to be an identifier.
                              >
                              >>It's definitely an identifier.
                              >
                              Obviously "errno" is an identifier. I should have said that it's a
                              macro that doesn't have to expand to an identifier.
                              >
                              >>However, it might not be the name of a variable with external linkage.
                              >
                              It might not expand to the name of a variable at all.
                              Right. That's one way that it might not be the name of a
                              variable with external linkage.
                              --
                              char a[]="\n .CJacehknorstu" ;int putchar(int);in t main(void){unsi gned long b[]
                              ={0x67dffdff,0x 9aa9aa6a,0xa77f fda9,0x7da6aa6a ,0xa67f6aaa,0xa a9aa9f6,0x11f6} ,*p
                              =b,i=24;for(;p+ =!*p;*p/=4)switch(0[p]&3)case 0:{return 0;for(p--;i--;i--)case+
                              2:{i++;if(i)bre ak;else default:continu e;if(0)case 1:putchar(a[i&15]);break;}}}

                              Comment

                              Working...