const array declaration

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

    const array declaration

    Hi guys,

    In a program (not my own) I encountered the declaration of a constant
    pointer to an array consisting of two other const pointers to arrays.
    Not quite sure why they do it so complicated, but is it legal? Most
    compilers accept it, but one doesn't recognize the rhs as a constant.
    What are the requirements for the rhs in the declaration of a const
    pointer? Is the following program legal C?

    int main(int argc, char *argv[]) {
    const char *a[] = {"A"};
    const char *b[] = {"B"};
    const char **z[] = {a, b}; /* this is the statement in question */
    return (0);
    }

    The error message is
    "t.c", line 4: error: initialization: constant expression is expected
    for variable: `z'

    Thanks in advance,

    Herbert
  • Tom St Denis

    #2
    Re: const array declaration


    "herbertF" <hfruchtl@yahoo .co.uk> wrote in message
    news:8d4b67c8.0 402091038.69ef7 5f8@posting.goo gle.com...[color=blue]
    > Hi guys,
    >
    > In a program (not my own) I encountered the declaration of a constant
    > pointer to an array consisting of two other const pointers to arrays.
    > Not quite sure why they do it so complicated, but is it legal? Most
    > compilers accept it, but one doesn't recognize the rhs as a constant.
    > What are the requirements for the rhs in the declaration of a const
    > pointer? Is the following program legal C?
    >
    > int main(int argc, char *argv[]) {
    > const char *a[] = {"A"};
    > const char *b[] = {"B"};
    > const char **z[] = {a, b}; /* this is the statement in question */
    > return (0);
    > }[/color]

    Your const was in the wrong spot.

    int main(int argc, char *argv[]) {
    char const *a[] = {"A"};
    char const *b[] = {"B"};
    char const **z[] = {a, b}; /* this is the statement in question */
    return (0);
    }

    Works just fine.

    Tom


    Comment

    • Eric Sosman

      #3
      Re: const array declaration

      herbertF wrote:[color=blue]
      >
      > Hi guys,
      >
      > In a program (not my own) I encountered the declaration of a constant
      > pointer to an array consisting of two other const pointers to arrays.
      > Not quite sure why they do it so complicated, but is it legal? Most
      > compilers accept it, but one doesn't recognize the rhs as a constant.
      > What are the requirements for the rhs in the declaration of a const
      > pointer? Is the following program legal C?
      >
      > int main(int argc, char *argv[]) {
      > const char *a[] = {"A"};
      > const char *b[] = {"B"};
      > const char **z[] = {a, b}; /* this is the statement in question */
      > return (0);
      > }
      >
      > The error message is
      > "t.c", line 4: error: initialization: constant expression is expected
      > for variable: `z'[/color]

      The complaining compiler is correct: `a' and `b' are not
      constant expressions.
      Despite the spelling, `const' is not
      "constant."

      If you think about it in a wider context, you'll see why
      `a' and `b' are not constant. Here's a recursive function
      with a similar construct, to help show what's happening:

      void func(int x) {
      const char *a[] = { "A", "B" };
      if (0 <= x && x < 2) {
      a[x] = "X";
      printf ("func(%d): a[0] = %s, a[1] = %s\n",
      x, a[0], a[1]);
      func (x + 1);
      printf ("func(%d): a[0] = %s, a[1] = %s\n",
      x, a[0], a[1]);
      }
      else {
      printf ("func(%d): nothing to do\n", x);
      }
      }

      If you call this function with `func(0)', the output will be

      func(0): a[0] = X, a[1] = B
      func(1): a[0] = A, a[1] = X
      func(2): nothing to do
      func(1): a[0] = A, a[1] = X
      func(0): a[0] = X, a[1] = B

      This shows that two different `a' arrays exist: one in
      the outer func(0) invocation, and another in the inner func(1).
      You can see that there must be more than one `a[]' because
      when the outer func(0) executes `a[0] = "X"' the value of `a[0]'
      in the inner func(1) is not affected; likewise when the inner
      func(1) sets `a[1] = "X"' it does not change `a[1]' in the
      outer func(0). Each `a[]' array comes into existence when its
      invocation of func() begins, and ceases to exist when its own
      func() returns. Thus, even though `a' is just one identifier,
      it designates different array objects at different times and
      is therefore not a constant.

      If you changed the function to declare the array as

      static const char *a[] = { "A", "B" };

      you would get a different output altogether:

      func(0): a[0] = X, a[1] = B
      func(1): a[0] = X, a[1] = X
      func(2): nothing to do
      func(1): a[0] = X, a[1] = X
      func(0): a[0] = X, a[1] = X

      In this case there is only one `a[]' array, and any changes
      made to it in one func() invocation are seen in the other. The
      lifetime of this single `a[]' is no longer tied to the execution
      of its containing block; this `a[]' comes into existence before
      the program starts executing and continues to exist until the
      program terminates. In this case, `a' *is* a constant, because
      the identifier refers to just one object for the entire time the
      program is running. If the one-and-only-one semantics make sense
      for your original program, perhaps the cure is to add the `static'
      qualifier.

      By the way, the non-complaining compilers are not in error.
      A compiler is *permitted* to allow non-constant initializers in
      addition to the constant initializers required by the Standard.

      --
      Eric.Sosman@sun .com

      Comment

      • Tom St Denis

        #4
        Re: const array declaration


        "Eric Sosman" <Eric.Sosman@su n.com> wrote in message
        news:4027DC17.8 D452099@sun.com ...
        [color=blue]
        > The complaining compiler is correct: `a' and `b' are not
        > constant expressions.
        > Despite the spelling, `const' is not
        > "constant."[/color]

        Yes it is. There is just a diff between

        const char *varname;

        and

        char const *varname;

        The former means the values in varname[...] are constant. E.g.

        varname[0] = 'a';

        will produce a warning.

        In the latter the actual pointer "varname" is constant so

        varname = &somebuf;

        will produce a warning while

        varname[0] = 'a';

        will not.

        const char const *varname;

        will make both constant.

        Tom


        Comment

        • Alex Monjushko

          #5
          Re: const array declaration

          Tom St Denis <tom@securescie nce.net> wrote:
          [color=blue]
          > "Eric Sosman" <Eric.Sosman@su n.com> wrote in message
          > news:4027DC17.8 D452099@sun.com ...[/color]
          [color=blue][color=green]
          >> The complaining compiler is correct: `a' and `b' are not
          >> constant expressions.
          >> Despite the spelling, `const' is not
          >> "constant."[/color][/color]
          [color=blue]
          > Yes it is. There is just a diff between[/color]
          [color=blue]
          > const char *varname;[/color]
          [color=blue]
          > and[/color]
          [color=blue]
          > char const *varname;[/color]

          These two forms are absolutely equivalent. For the latter you must
          be thinking about something like

          char * const varname;
          [color=blue]
          > The former means the values in varname[...] are constant. E.g.[/color]
          [color=blue]
          > varname[0] = 'a';[/color]
          [color=blue]
          > will produce a warning.[/color]

          .... and invoke undefined behavior since varname is not
          pointing at anything, but I digress.
          [color=blue]
          > In the latter the actual pointer "varname" is constant so[/color]

          Not true. See my comment above.
          [color=blue]
          > const char const *varname;[/color]

          This is exactly equivalent to:

          const const char *varname;

          Which is obviously wrong. Again, what you obviously meant to write:

          const char * const varname;

          --
          Alex Monjushko (monjushko@hotm ail.com)

          Comment

          • E. Robert Tisdale

            #6
            Re: const array declaration

            herbertF wrote:
            [color=blue]
            > In a program (not my own) I encountered the declaration of a constant
            > pointer to an array consisting of two other const pointers to arrays.
            > Not quite sure why they do it so complicated, but is it legal? Most
            > compilers accept it, but one doesn't recognize the rhs as a constant.
            > What are the requirements for the rhs in the declaration of a const
            > pointer? Is the following program legal C?
            >
            > int main(int argc, char *argv[]) {
            > const char *a[] = {"A"};
            > const char *b[] = {"B"};
            > const char **z[] = {a, b}; /* this is the statement in question */
            > return (0);
            > }
            >
            > The error message is
            > "t.c", line 4: error: initialization:
            > constant expression is expected for variable: `z'[/color]

            Let me try:
            [color=blue]
            > cat main.c[/color]
            int main(int argc, char* argv[]) {
            const char* const a[] = {"A"};
            const char* const b[] = {"B"};
            const char* const *z[] = {a, b};
            return 0;
            }
            [color=blue]
            > gcc -Wall -std=c99 -pedantic -o main main.c[/color]
            main.c: In function `main':
            main.c:6: warning: unused variable `z'

            It seems to work just fine.

            Comment

            • Tom St Denis

              #7
              Re: const array declaration


              "Alex Monjushko" <monjushko@hotm ail.com> wrote in message
              news:c08oiq$139 a9a$1@ID-190529.news.uni-berlin.de...[color=blue]
              > Tom St Denis <tom@securescie nce.net> wrote:
              >[color=green]
              > > "Eric Sosman" <Eric.Sosman@su n.com> wrote in message
              > > news:4027DC17.8 D452099@sun.com ...[/color]
              >[color=green][color=darkred]
              > >> The complaining compiler is correct: `a' and `b' are not
              > >> constant expressions.
              > >> Despite the spelling, `const' is not
              > >> "constant."[/color][/color]
              >[color=green]
              > > Yes it is. There is just a diff between[/color]
              >[color=green]
              > > const char *varname;[/color]
              >[color=green]
              > > and[/color]
              >[color=green]
              > > char const *varname;[/color]
              >
              > These two forms are absolutely equivalent. For the latter you must
              > be thinking about something like
              >
              > char * const varname;[/color]

              Yeah, oops.

              Tom


              Comment

              • nrk

                #8
                Re: const array declaration

                Tom St Denis wrote:
                [color=blue]
                >
                > "Eric Sosman" <Eric.Sosman@su n.com> wrote in message
                > news:4027DC17.8 D452099@sun.com ...
                >[color=green]
                >> The complaining compiler is correct: `a' and `b' are not
                >> constant expressions.
                >> Despite the spelling, `const' is not
                >> "constant."[/color]
                >
                > Yes it is. There is just a diff between
                >[/color]

                Bad Tom!! "Here be dragons" :-)
                [color=blue]
                > const char *varname;
                >
                > and
                >
                > char const *varname;
                >
                > The former means the values in varname[...] are constant. E.g.
                >[/color]

                Nope. Both mean exactly the same thing. Perhaps you wanted to show the
                difference between:
                const char *varname;
                and
                char * const varname;

                Former is a pointer to a const char, the latter a const pointer to char.
                [color=blue]
                > varname[0] = 'a';
                >
                > will produce a warning.
                >
                > In the latter the actual pointer "varname" is constant so
                >
                > varname = &somebuf;
                >
                > will produce a warning while
                >
                > varname[0] = 'a';
                >
                > will not.
                >
                > const char const *varname;
                >
                > will make both constant.
                >[/color]

                Nope. What you're looking for is:
                const char * const varname;

                Which makes varname a const pointer to const char.

                -nrk.
                [color=blue]
                > Tom[/color]

                --
                Remove devnull for email

                Comment

                • Richard Heathfield

                  #9
                  Re: const array declaration

                  Tom St Denis wrote:
                  [color=blue]
                  >
                  > "Eric Sosman" <Eric.Sosman@su n.com> wrote in message
                  > news:4027DC17.8 D452099@sun.com ...
                  >[color=green]
                  >> The complaining compiler is correct: `a' and `b' are not
                  >> constant expressions.
                  >> Despite the spelling, `const' is not
                  >> "constant."[/color]
                  >
                  > Yes it is. There is just a diff between
                  >
                  > const char *varname;
                  >
                  > and
                  >
                  > char const *varname;[/color]

                  No, not really. Both mean: "varname is a pointer to const char".
                  [color=blue]
                  >
                  > The former means the values in varname[...] are constant. E.g.
                  >
                  > varname[0] = 'a';
                  >
                  > will produce a warning.
                  >
                  > In the latter the actual pointer "varname" is constant so
                  >
                  > varname = &somebuf;
                  >
                  > will produce a warning while
                  >
                  > varname[0] = 'a';
                  >
                  > will not.
                  >
                  > const char const *varname;
                  >
                  > will make both constant.[/color]

                  No.

                  const char *varname;

                  and

                  char const *varname;

                  both mean the same thing - a pointer to const char. If you want a const
                  pointer to char, you need:

                  char * const varname;

                  --
                  Richard Heathfield : binary@eton.pow ernet.co.uk
                  "Usenet is a strange place." - Dennis M Ritchie, 29 July 1999.
                  C FAQ: http://www.eskimo.com/~scs/C-faq/top.html
                  K&R answers, C books, etc: http://users.powernet.co.uk/eton

                  Comment

                  • Jack Klein

                    #10
                    Re: const array declaration

                    On Mon, 09 Feb 2004 19:10:46 GMT, "Tom St Denis"
                    <tom@securescie nce.net> wrote in comp.lang.c:
                    [color=blue]
                    >
                    > "herbertF" <hfruchtl@yahoo .co.uk> wrote in message
                    > news:8d4b67c8.0 402091038.69ef7 5f8@posting.goo gle.com...[color=green]
                    > > Hi guys,
                    > >
                    > > In a program (not my own) I encountered the declaration of a constant
                    > > pointer to an array consisting of two other const pointers to arrays.
                    > > Not quite sure why they do it so complicated, but is it legal? Most
                    > > compilers accept it, but one doesn't recognize the rhs as a constant.
                    > > What are the requirements for the rhs in the declaration of a const
                    > > pointer? Is the following program legal C?
                    > >
                    > > int main(int argc, char *argv[]) {
                    > > const char *a[] = {"A"};
                    > > const char *b[] = {"B"};
                    > > const char **z[] = {a, b}; /* this is the statement in question */
                    > > return (0);
                    > > }[/color]
                    >
                    > Your const was in the wrong spot.
                    >
                    > int main(int argc, char *argv[]) {
                    > char const *a[] = {"A"};
                    > char const *b[] = {"B"};
                    > char const **z[] = {a, b}; /* this is the statement in question */
                    > return (0);
                    > }
                    >
                    > Works just fine.
                    >
                    > Tom[/color]

                    There is no difference at all between "const type" and "type const" in
                    a declarator.

                    --
                    Jack Klein
                    Home: http://JK-Technology.Com
                    FAQs for
                    comp.lang.c http://www.eskimo.com/~scs/C-faq/top.html
                    comp.lang.c++ http://www.parashift.com/c++-faq-lite/
                    alt.comp.lang.l earn.c-c++

                    Comment

                    • Jack Klein

                      #11
                      Re: const array declaration

                      On Mon, 09 Feb 2004 19:43:36 GMT, "Tom St Denis"
                      <tom@securescie nce.net> wrote in comp.lang.c:
                      [color=blue]
                      >
                      > "Eric Sosman" <Eric.Sosman@su n.com> wrote in message
                      > news:4027DC17.8 D452099@sun.com ...
                      >[color=green]
                      > > The complaining compiler is correct: `a' and `b' are not
                      > > constant expressions.
                      > > Despite the spelling, `const' is not
                      > > "constant."[/color]
                      >
                      > Yes it is. There is just a diff between
                      >
                      > const char *varname;
                      >
                      > and
                      >
                      > char const *varname;
                      >
                      > The former means the values in varname[...] are constant. E.g.
                      >
                      > varname[0] = 'a';
                      >
                      > will produce a warning.
                      >
                      > In the latter the actual pointer "varname" is constant so
                      >
                      > varname = &somebuf;
                      >
                      > will produce a warning while
                      >
                      > varname[0] = 'a';
                      >
                      > will not.
                      >
                      > const char const *varname;
                      >
                      > will make both constant.
                      >
                      > Tom[/color]

                      Look on the bright side, Tom. I did this once in comp.lang.c, years
                      ago, and had my *ss handed to me. I'll never make that particular
                      mistake again. I doubt you will, either.

                      --
                      Jack Klein
                      Home: http://JK-Technology.Com
                      FAQs for
                      comp.lang.c http://www.eskimo.com/~scs/C-faq/top.html
                      comp.lang.c++ http://www.parashift.com/c++-faq-lite/
                      alt.comp.lang.l earn.c-c++

                      Comment

                      • herbertF

                        #12
                        Re: const array declaration

                        Thanks for the lengthy discussion, but it seems like the question is
                        still not anwered. What I've learnt from it so far is that the "const"
                        seems to refer to the array elements, not the pointers themselves.
                        However, if I add another "const" level, the error message remains the
                        same. For completeness, here again the original program:

                        int main(int argc, char *argv[]) {
                        const char *a[] = {"A"};
                        const char *b[] = {"B"};
                        const char **z[] = {a, b};
                        return (0);
                        }

                        and the modified one:

                        int main(int argc, char *argv[]) {
                        const char * const a[] = {"A"};
                        const char * const b[] = {"B"};
                        const char * const *z[] = {a, b};
                        return (0);
                        }

                        The error message I'm getting is
                        "t.c", line 4: error: initialization: constant expression is expected
                        for variable: `z'

                        Gcc with -pedantic also reports an error:
                        t.c:4: initializer element is not computable at load time
                        t.c:4: (near initialization for `z[0]')
                        t.c:4: initializer element is not computable at load time
                        t.c:4: (near initialization for `z[1]')

                        Again the question: is this legal C, and if not, how can it be made
                        legal?

                        TiA,

                        Herbert

                        Comment

                        • Richard Bos

                          #13
                          Re: const array declaration

                          hfruchtl@yahoo. co.uk (herbertF) wrote:
                          [color=blue]
                          > Thanks for the lengthy discussion, but it seems like the question is
                          > still not anwered.[/color]

                          Actually, it is.
                          [color=blue]
                          > What I've learnt from it so far is that the "const"
                          > seems to refer to the array elements, not the pointers themselves.
                          > However, if I add another "const" level, the error message remains the
                          > same. For completeness, here again the original program:
                          >
                          > int main(int argc, char *argv[]) {
                          > const char *a[] = {"A"};
                          > const char *b[] = {"B"};[/color]

                          What you've also learned is that, despite having the keyword "const"
                          somewhere in their definitions, these objects are not compile-time
                          constants, so...
                          [color=blue]
                          > const char **z[] = {a, b};[/color]

                          ....they cannot be used as initialisers. No amount of const-qualifying,
                          whether of the pointers themselves or of their underlying types, can
                          change that.

                          Richard

                          Comment

                          • Chris Mantoulidis

                            #14
                            Re: const array declaration

                            > int main(int argc, char *argv[]) {[color=blue]
                            > const char *a[] = {"A"};
                            > const char *b[] = {"B"};
                            > const char **z[] = {a, b};
                            > return (0);
                            > }
                            >
                            > and the modified one:
                            >
                            > int main(int argc, char *argv[]) {
                            > const char * const a[] = {"A"};
                            > const char * const b[] = {"B"};
                            > const char * const *z[] = {a, b};
                            > return (0);
                            > }
                            >
                            > The error message I'm getting is
                            > "t.c", line 4: error: initialization: constant expression is expected
                            > for variable: `z'
                            >
                            > Gcc with -pedantic also reports an error:
                            > t.c:4: initializer element is not computable at load time
                            > t.c:4: (near initialization for `z[0]')
                            > t.c:4: initializer element is not computable at load time
                            > t.c:4: (near initialization for `z[1]')[/color]

                            Okay, this is really weird. here are the 2 programs I compiled:

                            (1)
                            int main(int argc, char **argv) {
                            const char *a[] = {"A"}; //constant pointer
                            const char *b[] = {"B"};
                            const char **z[] = {a, b};
                            return 0;
                            }

                            and (2)
                            int main(int argc, char **argv) {
                            const char *const a[] = {"A"}; //constant pointer AND constand data
                            const char *const b[] = {"B"};
                            const char *const *z[] = {a,b};
                            return 0;
                            }
                            -----

                            I compiled both with GCC 3.3.2 like
                            $gcc -Wall -std=c99 -pedantic const_test_1.c
                            $gcc -Wall -std=c99 -pedantic const_test_2.c

                            Only reply I got was:
                            const_test_1.c: In function "main":
                            const_test_1.c: 4: warning: unused variable `z'
                            (the same for the other file)

                            What compiler do you have? I don't see why yours complains :/

                            Comment

                            • herbertF

                              #15
                              Re: const array declaration

                              I think I found the answer myself. Could somebody comment if my
                              conclusions are correct? Here are the relevant paragraphs from the
                              (draft) C99 standard:

                              6.2.4 Storage duration of objects, paragraph 4:
                              For such an object that does not have a variable length array type,
                              storage is guaranteed to be reserved for a new instance of the object
                              on each entry into the block with which it is associated; the initial
                              value of the object is indeterminate. If an initialization is
                              specified for the object, it is performed each time the declaration is
                              reached in the execution of the block; otherwise, the value becomes
                              indeterminate each time the declaration is reached. Storage for the
                              object is no longer guaranteed to be reserved when execution of the
                              block ends in any way. (Entering an enclosed block or calling a
                              function suspends, but does not end, execution of the current block.)

                              6.6, paragraph 2:

                              A constant expression can be evaluated during translation rather than
                              runtime, and accordingly may be used in any place that a constant may
                              be.

                              Paragraph 10:

                              An implementation may accept other forms of constant expressions.

                              6.7.8 Initialization, paragraph 1:
                              Syntax
                              initializer:
                              assignment-expression
                              { initializer-list }
                              { initializer-list , }
                              initializer-list:
                              designationopt initializer
                              initializer-list , designationopt initializer
                              designation:
                              designator-list =
                              designator-list:
                              designator
                              designator-list designator
                              designator:
                              [ constant-expression ]
                              . identifier

                              The conclusion is that, because a and b are not static, their
                              addresses are not known at compile or load time (and may change
                              between calls to the routine in question), so they are not allowed in
                              the "designator " part of an initialisation expression, which has to be
                              a constant expression. Compilers who think they know enough may allow
                              it (6.6, paragraph 10). To make it fully portable, the static
                              qualifier has to be present for a and b (in addition to const).

                              Is this correct?

                              Btw., I found this about the much discussed question of where in the
                              line "const" goes:

                              6.7.3 Type qualifiers, paragraph 8:

                              If the specification of an array type includes any type qualifiers,
                              the element type is so qualified, not the array type. If the
                              specification of a function type includes any type qualifiers, the
                              behavior is undefined.

                              H.

                              Comment

                              Working...