Vexing GCC warnings: "assignment discards qualifiers from pointertarget type"

Discussion in 'C Programming' started by Charlie Zender, Jan 2, 2004.

  1. Hi,

    I am unable to compile a large body of code with extremely pedantic
    compile time checks activate, so that warnings cause errors.
    With GCC 3.3.1, I do this with

    gcc -std=c99 -pedantic -Wall -Wunused -Werror -W -Wmissing-prototypes
    -Wconversion -Wshadow -Wpointer-arith -Wcast-qual -Wcast-align
    -Wwrite-strings -c -o foo.o foo.c

    (This is basically what GSL recommendsd for scientific codes.)

    The problem is that I have a lot of code that generates these warnings:

    foo.c:258: warning: "assignment discards qualifiers from pointer target
    type"

    This warning occurs when I try to return string literals (e.g., error
    messages) to a calling function. Currently, I use code like

    char * err_sng(const int err_nbr){
    switch(err_nbr){
    case 0: return "Message 0";
    case 1: return "Message 1";
    }
    }

    1. Say you have a function whose purpose is to return a constant
    string literal (e.g., an error message) to a calling function.
    How would you write this type of function so as not to generate
    "assignment discards qualifiers" warnings?

    Note that these warnings disappear if I prototype the function as

    const char * err_sng(int err_nbr);

    Is that legal? I suspect that qualifying a return value is a GNUism
    and am not sure if there is a preferred method that avoids this
    dubious prototype.

    Any help appreciated,
    Charlie
    --
    Charlie Zender, , (949) 824-2987, Department of Earth
    System Science, University of California, Irvine CA 92697-3100
    Visiting NCAR 12/13/03--1/17/04: ***********************************
    Voice/FAX: (303) 497-1724/1348, Office: Mesa Lab 259b **************
    Charlie Zender, Jan 2, 2004
    #1
    1. Advertising

  2. Re: Vexing GCC warnings: "assignment discards qualifiers from pointer target type"

    "Charlie Zender" <> wrote in message
    news:...
    > The problem is that I have a lot of code that generates these warnings:
    >
    > foo.c:258: warning: "assignment discards qualifiers from pointer target
    > type"
    >
    > This warning occurs when I try to return string literals (e.g., error
    > messages) to a calling function. Currently, I use code like
    >
    > char * err_sng(const int err_nbr){
    > switch(err_nbr){
    > case 0: return "Message 0";
    > case 1: return "Message 1";
    > }
    > }
    >
    > 1. Say you have a function whose purpose is to return a constant
    > string literal (e.g., an error message) to a calling function.
    > How would you write this type of function so as not to generate
    > "assignment discards qualifiers" warnings?


    return const char * instead of char *.

    > Note that these warnings disappear if I prototype the function as
    >
    > const char * err_sng(int err_nbr);


    See? I told you!

    > Is that legal? I suspect that qualifying a return value is a GNUism
    > and am not sure if there is a preferred method that avoids this
    > dubious prototype.


    Dubious? Where have you been the last 15 years?

    Seriously, string literals in C have a type char[], not const char[] as one
    would expect when trying to modify them causes a UB. GCC probably realizes
    that and tries to prevent you from doing something stupid by warning about
    returning a string literal as char * without const.

    Hope this helps,

    Peter
    Peter Pichler, Jan 2, 2004
    #2
    1. Advertising

  3. Thanks.

    > Dubious? Where have you been the last 15 years?


    My experience has been that some compilers warned about qualifiers on
    return values in function prototypes. This was some time ago, though,
    and they may have been C++ compilers, I can't remember.
    Anyway, if it's legal, then great, it fixes the problem perfectly.

    > Seriously, string literals in C have a type char[], not const char[] as one
    > would expect when trying to modify them causes a UB. GCC probably realizes
    > that and tries to prevent you from doing something stupid by warning about
    > returning a string literal as char * without const.


    Yes, agreed.

    > Hope this helps,


    It does. I've got another question to post soon...

    Charlie
    --
    Charlie Zender, , (949) 824-2987, Department of Earth
    System Science, University of California, Irvine CA 92697-3100
    Visiting NCAR 12/13/03--1/17/04: ***********************************
    Voice/FAX: (303) 497-1724/1348, Office: Mesa Lab 259b **************
    Charlie Zender, Jan 2, 2004
    #3
  4. Charlie Zender wrote:
    > Hi,
    >
    > I am unable to compile a large body of code with extremely pedantic
    > compile time checks activate, so that warnings cause errors.
    > With GCC 3.3.1, I do this with
    >
    > gcc -std=c99 -pedantic -Wall -Wunused -Werror -W -Wmissing-prototypes
    > -Wconversion -Wshadow -Wpointer-arith -Wcast-qual -Wcast-align
    > -Wwrite-strings -c -o foo.o foo.c
    >
    > (This is basically what GSL recommendsd for scientific codes.)
    >
    > The problem is that I have a lot of code that generates these warnings:
    >
    > foo.c:258: warning: "assignment discards qualifiers from pointer target
    > type"
    >
    > This warning occurs when I try to return string literals (e.g., error
    > messages) to a calling function. Currently, I use code like
    >
    > char * err_sng(const int err_nbr){
    > switch(err_nbr){
    > case 0: return "Message 0";
    > case 1: return "Message 1";
    > }
    > }


    #include <stdio.h>
    const char *err_sng(const int err_nbr)
    {
    switch (err_nbr) {
    case 0:
    return "Message 0";
    case 1:
    return "Message 1";
    default:
    return "Huh?";
    }
    }

    int main(void)
    {
    fprintf(stderr, "%s\n", err_sng(0));
    fprintf(stderr, "%s\n", err_sng(1));
    fprintf(stderr, "%s\n", err_sng(2));
    return 0;
    }


    [output]


    Message 0
    Message 1
    Huh?



    > Note that these warnings disappear if I prototype the function as
    >
    > const char * err_sng(int err_nbr);
    >
    > Is that legal?


    yes



    --
    Martin Ambuhl
    Martin Ambuhl, Jan 2, 2004
    #4
  5. Charlie Zender

    Jack Klein Guest

    Re: Vexing GCC warnings: "assignment discards qualifiers from pointer target type"

    On Fri, 02 Jan 2004 12:42:43 -0800, Charlie Zender <>
    wrote in comp.lang.c:

    > Hi,
    >
    > I am unable to compile a large body of code with extremely pedantic
    > compile time checks activate, so that warnings cause errors.
    > With GCC 3.3.1, I do this with
    >
    > gcc -std=c99 -pedantic -Wall -Wunused -Werror -W -Wmissing-prototypes
    > -Wconversion -Wshadow -Wpointer-arith -Wcast-qual -Wcast-align
    > -Wwrite-strings -c -o foo.o foo.c
    >
    > (This is basically what GSL recommendsd for scientific codes.)
    >
    > The problem is that I have a lot of code that generates these warnings:
    >
    > foo.c:258: warning: "assignment discards qualifiers from pointer target
    > type"
    >
    > This warning occurs when I try to return string literals (e.g., error
    > messages) to a calling function. Currently, I use code like
    >
    > char * err_sng(const int err_nbr){
    > switch(err_nbr){
    > case 0: return "Message 0";
    > case 1: return "Message 1";
    > }
    > }
    >
    > 1. Say you have a function whose purpose is to return a constant
    > string literal (e.g., an error message) to a calling function.
    > How would you write this type of function so as not to generate
    > "assignment discards qualifiers" warnings?
    >
    > Note that these warnings disappear if I prototype the function as
    >
    > const char * err_sng(int err_nbr);
    >
    > Is that legal? I suspect that qualifying a return value is a GNUism
    > and am not sure if there is a preferred method that avoids this
    > dubious prototype.


    In addition to what Peter said, correctly, I wanted to address this
    last question. Qualifying a return value is perfectly valid,
    harmless, and useless in standard C, and is not just a GNU thing.

    But you have not qualified the returned value, which is a pointer. If
    you wanted to do that, you would need to code:

    char * const err_sng(int err_nbr);

    ....which would be, as I said, valid, harmless, and useless.

    What you specify here is not that the pointer is constant, but that
    the characters it points to are.

    Consider the two functions:

    char *f1(char *cp)
    {
    return cp;
    }

    const char *f2(char *cp)
    {
    return cp;
    }

    Given the above function definitions/prototypes and this definition:

    char non_const [] = "Hello, World!";

    *f1(non_const) = 'h'; /* legal, changes to "hello, World!" */

    *f2(non_const) = 'h'; /* illegal, requires diagnostic */

    --
    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.learn.c-c++ ftp://snurse-l.org/pub/acllc-c /faq
    Jack Klein, Jan 2, 2004
    #5
  6. Charlie Zender

    Ben Pfaff Guest

    Re: Vexing GCC warnings: "assignment discards qualifiers from pointer target type"

    Charlie Zender <> writes:

    > Hi,
    >
    > I am unable to compile a large body of code with extremely pedantic
    > compile time checks activate, so that warnings cause errors.
    > With GCC 3.3.1, I do this with
    >
    > gcc -std=c99 -pedantic -Wall -Wunused -Werror -W -Wmissing-prototypes
    > -Wconversion -Wshadow -Wpointer-arith -Wcast-qual -Wcast-align
    > -Wwrite-strings -c -o foo.o foo.c


    Here is your problem. In C, string literals have type `char []'.
    When -Wwrite-strings is used, GCC is not a C compiler, because
    string literals have type `const char []'. Here is the
    appropriate section from the GCC manual that talks about it:

    `-Wwrite-strings'
    When compiling C, give string constants the type `const
    char[LENGTH]' so that copying the address of one into a
    non-`const' `char *' pointer will get a warning; when
    compiling C++, warn about the deprecated conversion from
    string constants to `char *'. These warnings will help
    you find at compile time code that can try to write into
    a string constant, but only if you have been very
    careful about using `const' in declarations and
    prototypes. Otherwise, it will just be a nuisance; this
    is why we did not make `-Wall' request these warnings.

    Don't use -Wwrite-strings if you want to compile C.

    > Note that these warnings disappear if I prototype the function as
    >
    > const char * err_sng(int err_nbr);
    >
    > Is that legal? I suspect that qualifying a return value is a GNUism
    > and am not sure if there is a preferred method that avoids this
    > dubious prototype.


    No, `const char *' is a portable return type. I'm not sure why
    you think it's a GNUism, but it isn't.
    --
    "This is a wonderful answer.
    It's off-topic, it's incorrect, and it doesn't answer the question."
    --Richard Heathfield
    Ben Pfaff, Jan 2, 2004
    #6
  7. Peter Pichler wrote:
    >
    > Seriously, string literals in C have a type char[], not const char[] as one
    > would expect when trying to modify them causes a UB. GCC probably realizes
    > that and tries to prevent you from doing something stupid by warning about
    > returning a string literal as char * without const.


    <OT> gcc gives string literals the type 'const char[]' if you ask it to
    by using the -Wwrite-strings option (which the OP did). Personally I
    think this is a very good option to have enabled (though possibly not if
    you are compiling older code). </OT>

    -Kevin
    --
    My email address is valid, but changes periodically.
    To contact me please use the address from a recent posting.
    Kevin Goodsell, Jan 2, 2004
    #7
  8. Charlie Zender wrote:

    > Thanks.
    >
    >> Dubious? Where have you been the last 15 years?

    >
    >
    > My experience has been that some compilers warned about qualifiers on
    > return values in function prototypes. This was some time ago, though,
    > and they may have been C++ compilers, I can't remember.
    > Anyway, if it's legal, then great, it fixes the problem perfectly.


    That might make sense if it was something like this:

    const int f(void);

    Because that's silly. But in the case of a pointer, the 'const'
    (depending on placement) refers to the thing pointer to, not the pointer
    itself. This is perfectly reasonable, and often a good idea.

    -Kevin
    --
    My email address is valid, but changes periodically.
    To contact me please use the address from a recent posting.
    Kevin Goodsell, Jan 2, 2004
    #8
  9. Ahhh. Thanks for the clarification. Now I see that I can qualify
    things that return values point to, but not the return values
    themselves. That makes good sense to me. And it explains why I
    remember getting warnings before. I was probably trying to qualify
    returned pointers rather than the values pointed to because I
    remember the warning said something about the qualifiers being
    useless.

    > But you have not qualified the returned value, which is a pointer. If
    > you wanted to do that, you would need to code:
    >
    > char * const err_sng(int err_nbr);
    >
    > ...which would be, as I said, valid, harmless, and useless.
    >
    > What you specify here is not that the pointer is constant, but that
    > the characters it points to are.


    --
    Charlie Zender, , (949) 824-2987, Department of Earth
    System Science, University of California, Irvine CA 92697-3100
    Visiting NCAR 12/13/03--1/17/04: ***********************************
    Voice/FAX: (303) 497-1724/1348, Office: Mesa Lab 259b **************
    Charlie Zender, Jan 2, 2004
    #9
  10. Ben Pfaff wrote:

    >
    > Don't use -Wwrite-strings if you want to compile C.
    >


    I disagree with this. It's true that you'll be required to remove this
    option for some C code, but I think it's best in new code to treat
    string literals as const, regardless of whether they technically are or
    not. If you do so (or intend to do so), then this option is useful.

    I'd be interested to hear arguments to the contrary.

    -Kevin
    --
    My email address is valid, but changes periodically.
    To contact me please use the address from a recent posting.
    Kevin Goodsell, Jan 2, 2004
    #10
  11. Re: Vexing GCC warnings: "assignment discards qualifiers from pointer target type"

    Kevin Goodsell wrote:
    > Ben Pfaff wrote:
    >> Don't use -Wwrite-strings if you want to compile C.

    >
    > I disagree with this. It's true that you'll be required to remove this
    > option for some C code, but I think it's best in new code to treat
    > string literals as const, regardless of whether they technically are or
    > not. If you do so (or intend to do so), then this option is useful.
    >
    > I'd be interested to hear arguments to the contrary.


    With -Wwrite-strings, gcc silently accepts code that requires a
    diagnostic according to the standard. That is, with this option, gcc
    will cleanly compile programs that a conforming implementation may
    reject.

    Try setting gcc loose on the following with and without the
    -Wwrite-strings option.

    int f(const char (*p)[])
    {
    return !p;
    }

    int main()
    {
    return f(&"foo");
    }

    (For comparison, the Tendra compiler issues an error and doesn't
    generate any output:

    "string.c", line 8: Error:
    [ISO 6.3.2.2]: In call of function 'f'.
    [ISO 6.1.2.6]: The types 'char [4]' and 'const char []' are incompatible.
    [ISO 6.3.4]: Types in pointer conversion should be compatible.
    [ISO 6.3.16]: Can't perform this conversion by assignment.
    [ISO 6.3.2.2]: Argument 1 is converted to parameter type.
    )

    Jeremy.
    Jeremy Yallop, Jan 2, 2004
    #11
  12. Charlie Zender

    CBFalconer Guest

    Peter Pichler wrote:
    >

    .... snip ...
    >
    > Seriously, string literals in C have a type char[], not const
    > char[] as one would expect when trying to modify them causes a UB.
    > GCC probably realizes that and tries to prevent you from doing
    > something stupid by warning about returning a string literal as
    > char * without const.


    He specifically told it to with -Wwrite-strings.

    --
    Chuck F () ()
    Available for consulting/temporary embedded and systems.
    <http://cbfalconer.home.att.net> USE worldnet address!
    CBFalconer, Jan 2, 2004
    #12
  13. Re: Vexing GCC warnings: "assignment discards qualifiers from pointer target type"

    "CBFalconer" <> wrote:
    > Peter Pichler wrote:
    > > Seriously, string literals in C have a type char[], not const
    > > char[] as one would expect when trying to modify them causes a UB.
    > > GCC probably realizes that and tries to prevent you from doing
    > > something stupid by warning about returning a string literal as
    > > char * without const.

    >
    > He specifically told it to with -Wwrite-strings.


    <OT>Thanks, someone else has already said that (I think it was Ben Pfaff).
    Not being a gcc expert, I didn't know about that switch.</OT>
    Peter Pichler, Jan 3, 2004
    #13
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Charlie Zender

    Removing GCC compiler warnings from fabsf(), sqrtf()...

    Charlie Zender, Jan 2, 2004, in forum: C Programming
    Replies:
    8
    Views:
    617
    Ben Pfaff
    Jan 4, 2004
  2. Warnings with gcc

    , Nov 22, 2005, in forum: C Programming
    Replies:
    34
    Views:
    1,355
    Flash Gordon
    Nov 25, 2005
  3. asdf

    gcc warnings

    asdf, Jun 26, 2006, in forum: C++
    Replies:
    4
    Views:
    360
  4. ram

    vexing browser difference

    ram, Mar 4, 2004, in forum: Javascript
    Replies:
    0
    Views:
    76
  5. Ted Sung
    Replies:
    1
    Views:
    295
    Sherm Pendley
    Aug 30, 2004
Loading...

Share This Page