assigning string constant to char *

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

    #1

    assigning string constant to char *

    The first of the following functions compiles, the second gives what
    I think is a spurious error:

    "cannot convert `const char[5]' to `char *' in assignment".

    void foo(int m) {
    char *str;
    if (m < 4) str = "%01x";
    else if (m < 9) str = "%02x";
    else str = "%03x";
    }

    void foo(int m) {
    char *str;
    str = m < 4 ? "%01x" : m < 9 ? "%02x" : "%03x";
    }

    Any idea why gcc doesn't like the second version? If I compile
    it as a C file instead of C++, it works fine.

    Steve
  • Thomas Tutone

    #2
    Re: assigning string constant to char *

    Steve Pope wrote:
    The first of the following functions compiles, the second gives what
    I think is a spurious error:
    >
    "cannot convert `const char[5]' to `char *' in assignment".
    >
    void foo(int m) {
    char *str;
    if (m < 4) str = "%01x";
    else if (m < 9) str = "%02x";
    else str = "%03x";
    }
    >
    void foo(int m) {
    char *str;
    str = m < 4 ? "%01x" : m < 9 ? "%02x" : "%03x";
    }
    >
    Any idea why gcc doesn't like the second version? If I compile
    it as a C file instead of C++, it works fine.
    It is not a spurious error, just an obscure one. A string constant
    (like "%01x") is actually of type const char[5], which decays to const
    char*. For historical reasons (so as not to break a lot of existing
    code), you can assign a string constant to a non-const char*, although
    it bends (if not breaks) const-correctness. In the first example, you
    are assigning a string constant to a char*, and that's permitted. In
    the second example, you are assigning not a string constant, but an
    expression instead, to the char*. That's not permitted - the exception
    to const-correctness is intentionally kept narrow.

    To solve your problem change your second example to the following:

    void foo(int m) {
    const char *str = m < 4 ? "%01x" : m < 9 ? "%02x" : "%03x";
    }

    Since you're now assigning to a const char*, not to a non-const char*,
    the problem disappears.

    Best regards,

    Tom

    Comment

    • Steve Pope

      #3
      Re: assigning string constant to char *

      Thomas Tutone <Thomas8675309@ yahoo.comwrote:
      >Steve Pope wrote:
      >void foo(int m) {
      >char *str;
      >str = m < 4 ? "%01x" : m < 9 ? "%02x" : "%03x";
      >}
      >Any idea why gcc doesn't like the second version? If I compile
      >it as a C file instead of C++, it works fine.
      >It is not a spurious error, just an obscure one. A string constant
      >(like "%01x") is actually of type const char[5], which decays to const
      >char*. For historical reasons (so as not to break a lot of existing
      >code), you can assign a string constant to a non-const char*, although
      >it bends (if not breaks) const-correctness. In the first example, you
      >are assigning a string constant to a char*, and that's permitted. In
      >the second example, you are assigning not a string constant, but an
      >expression instead, to the char*. That's not permitted - the exception
      >to const-correctness is intentionally kept narrow.
      Okay, that makes sense.
      >To solve your problem change your second example to the following:
      >void foo(int m) {
      >const char *str = m < 4 ? "%01x" : m < 9 ? "%02x" : "%03x";
      >}
      >Since you're now assigning to a const char*, not to a non-const char*,
      >the problem disappears.
      That works, but oddly so does the following:

      const char *str;
      str = m < 4 ? "%01x" : m < 9 ? "%02x" : "%03x";
      if (m 12) str = "%04x";

      It seems the "const" does not mean as much for type char * as
      it does for other types.

      Steve
      >
      >Best regards,
      >
      >Tom
      >

      Comment

      • zeppe

        #4
        Re: assigning string constant to char *

        Steve Pope wrote:
        It seems the "const" does not mean as much for type char * as
        it does for other types.
        It's an issue related not to the char type, but to the string literals:
        the following conversion are allowed:
        string literal -const char*
        string literal -char* // deprecated, but valid

        but, of course, it's not valid
        const char* -char*

        so, you can convert string literal to char* only directly, not through
        const char* (as you tried with the conditional operator '?').

        Bye,

        Zeppe

        Comment

        • peter koch

          #5
          Re: assigning string constant to char *


          Steve Pope skrev:

          [snip]
          >
          Okay, that makes sense.
          >
          To solve your problem change your second example to the following:
          >
          void foo(int m) {
          const char *str = m < 4 ? "%01x" : m < 9 ? "%02x" : "%03x";
          }
          >
          Since you're now assigning to a const char*, not to a non-const char*,
          the problem disappears.
          >
          That works, but oddly so does the following:
          >
          const char *str;
          str = m < 4 ? "%01x" : m < 9 ? "%02x" : "%03x";
          if (m 12) str = "%04x";
          >
          It seems the "const" does not mean as much for type char * as
          it does for other types.
          Well no.... as Thomas Tutone explained, you can break constness for
          char only. But what surprises you above is that you can reassign str.
          This is because you read the type wrongly. const char *str means that
          str is a pointer to a constant char. The pointer is by itself not
          constant - you can assign it to anything you want (and actually you
          should be surprised by both assignments above). If you wanted the
          pointer to be constant, the notation would have to be char * const str
          (and then you better remember to initialise it!). This way the content
          of *str would be changeable.

          /Peter
          >
          Steve

          Best regards,

          Tom

          Comment

          • Thomas Tutone

            #6
            Re: assigning string constant to char *


            Steve Pope wrote:
            Thomas Tutone <Thomas8675309@ yahoo.comwrote:
            [snip]
            It is not a spurious error, just an obscure one. A string constant
            (like "%01x") is actually of type const char[5], which decays to const
            char*. For historical reasons (so as not to break a lot of existing
            code), you can assign a string constant to a non-const char*, although
            it bends (if not breaks) const-correctness. In the first example, you
            are assigning a string constant to a char*, and that's permitted. In
            the second example, you are assigning not a string constant, but an
            expression instead, to the char*. That's not permitted - the exception
            to const-correctness is intentionally kept narrow.
            >
            Okay, that makes sense.
            >
            To solve your problem change your second example to the following:
            >
            void foo(int m) {
            const char *str = m < 4 ? "%01x" : m < 9 ? "%02x" : "%03x";
            }
            >
            Since you're now assigning to a const char*, not to a non-const char*,
            the problem disappears.
            >
            That works, but oddly so does the following:
            >
            const char *str;
            str = m < 4 ? "%01x" : m < 9 ? "%02x" : "%03x";
            if (m 12) str = "%04x";
            >
            It seems the "const" does not mean as much for type char * as
            it does for other types.
            Sorry, my changing your example so that the str was initialized upon
            creation confused matters. A const char* means "a pointer to a char
            that is const," not "a const pointer to a char." The latter would be
            char* const. You can reassign a const char*, you just can't change the
            contents of what it points to.

            Best regards,

            Tom

            Comment

            • Victor Bazarov

              #7
              Re: assigning string constant to char *

              Steve Pope wrote:
              Thomas Tutone <Thomas8675309@ yahoo.comwrote:
              [..]
              >To solve your problem change your second example to the following:
              >
              >void foo(int m) {
              >const char *str = m < 4 ? "%01x" : m < 9 ? "%02x" : "%03x";
              >}
              >
              >Since you're now assigning to a const char*, not to a non-const
              >char*, the problem disappears.
              >
              That works, but oddly so does the following:
              >
              const char *str;
              str = m < 4 ? "%01x" : m < 9 ? "%02x" : "%03x";
              if (m 12) str = "%04x";
              >
              It seems the "const" does not mean as much for type char * as
              it does for other types.
              You confuse your consts. In

              const char * str;

              'const' relates to the char, not to the char*. You need to read up on
              declaration syntax and its meaning.

              V
              --
              Please remove capital 'A's when replying by e-mail
              I do not respond to top-posted replies, please don't ask


              Comment

              • Steve Pope

                #8
                Re: assigning string constant to char *

                zeppe <zeppe@nospam.r emove.all.this. email.itwrote:
                >Steve Pope wrote:
                >It seems the "const" does not mean as much for type char * as
                >it does for other types.
                It's an issue related not to the char type, but to the string
                literals: the following conversion are allowed:
                string literal -const char*
                string literal -char* // deprecated, but valid
                >
                >but, of course, it's not valid
                >const char* -char*
                >
                >so, you can convert string literal to char* only directly, not through
                >const char* (as you tried with the conditional operator '?').
                Seems that *is* related to the type char *, since the following
                code also compiles, whereas analogous code with str of any type
                other than char * does not compile. To me it looks like gcc
                at least has special-cased "const char *" to not actually be const.

                char a[10], b[10];

                void foo(int m) {
                const char *str;
                str = a;
                if (m 12) str = b;
                }

                Cheers,


                Steve

                Comment

                • Victor Bazarov

                  #9
                  Re: assigning string constant to char *

                  Steve Pope wrote:
                  [..] To me it looks like gcc
                  at least has special-cased "const char *" to not actually be const.
                  >
                  char a[10], b[10];
                  >
                  void foo(int m) {
                  const char *str;
                  str = a;
                  if (m 12) str = b;
                  }
                  There you go again... 'str' is a non-const pointer to const char.
                  You can assign new value to it from an array (which when used in
                  an exrpession like assignment above decays to a pointer to char).

                  If you want 'str' to be non-changeable pointer, you need to declare
                  *it itself* const:

                  char * const str;

                  V
                  --
                  Please remove capital 'A's when replying by e-mail
                  I do not respond to top-posted replies, please don't ask


                  Comment

                  • zeppe

                    #10
                    Re: assigning string constant to char *

                    Steve Pope wrote:
                    >but, of course, it's not valid
                    >const char* -char*
                    Seems that *is* related to the type char *, since the following
                    code also compiles, whereas analogous code with str of any type
                    other than char * does not compile. To me it looks like gcc
                    at least has special-cased "const char *" to not actually be const.
                    >
                    char a[10], b[10];
                    >
                    void foo(int m) {
                    const char *str;
                    str = a;
                    if (m 12) str = b;
                    }
                    Actually, this is the opposite cast, i.e.:
                    char* -const char*

                    that of course is correct (and the above code works also with int*,
                    double* and any other pointer).
                    BTW, it seems that we are talking about two different things: I was
                    explaining the strange behaviour due to the conversion from literal to
                    char*, and you are referring to the fact that is seems possible o change
                    value to a const variable (that is, as others explained, is not const,
                    but it's const the value the pointer is referring to).


                    Bye,

                    Zeppe

                    Comment

                    • Steve Pope

                      #11
                      Re: assigning string constant to char *

                      peter koch <peter.koch.lar sen@gmail.comwr ote:
                      >But what surprises you above is that you can reassign str.
                      >This is because you read the type wrongly. const char *str means that
                      >str is a pointer to a constant char. The pointer is by itself not
                      >constant - you can assign it to anything you want (and actually you
                      >should be surprised by both assignments above). If you wanted the
                      >pointer to be constant, the notation would have to be char * const str
                      >(and then you better remember to initialise it!).
                      Thanks, that does explain my confusion here.

                      Steve

                      Comment

                      Working...