Returning a pointer to a constant string

Discussion in 'C Programming' started by =?iso-8859-1?q?Santiago_Urue=F1a?=, Sep 17, 2007.

  1. Hi,

    I tried to return a pointer to a constant string, but the compiler
    gives the following warning if a cast is not used:

    warning: assignment from incompatible pointer type

    This is the code:


    const char msg[] = "Test message";

    const char *message(void) {
    return msg;
    }

    int main(void){
    const char * str;

    str = (const char *)message;
    str = (char *)message;
    str = message; /* GCC warning! */

    str = (const char *)msg;
    str = (char *)msg;
    str = msg;

    return 0;
    }

    Oddly, GCC only gives the warning if no cast is used, but it doesn't
    complain if the cast discards the const qualifier. Is this behavior
    OK? I'm using GCC 4.1.2. Thanks!

    Best regards,

    Santi
    =?iso-8859-1?q?Santiago_Urue=F1a?=, Sep 17, 2007
    #1
    1. Advertising

  2. In article <>,
    =?iso-8859-1?q?Santiago_Urue=F1a?= <> wrote:

    >I tried to return a pointer to a constant string, but the compiler
    >gives the following warning if a cast is not used:


    > warning: assignment from incompatible pointer type


    >This is the code:


    >const char msg[] = "Test message";


    >const char *message(void) {
    > return msg;
    >}


    Pay close attention to the placement of the const qualifiers.

    const char msg[] says that msg[someindex] will be a const char

    const char *message(void)

    says that message will return a pointer to a char and that the
    pointer is constant. (I think. I'm not -positive-. I haven't had
    much occasion to use const.)
    --
    All is vanity. -- Ecclesiastes
    Walter Roberson, Sep 17, 2007
    #2
    1. Advertising

  3. =?iso-8859-1?q?Santiago_Urue=F1a?=

    JimS Guest

    On Mon, 17 Sep 2007 15:38:15 -0700, Santiago Urueña
    <> wrote:

    >Hi,
    >
    >I tried to return a pointer to a constant string, but the compiler
    >gives the following warning if a cast is not used:
    >
    > warning: assignment from incompatible pointer type
    >
    >This is the code:
    >
    >
    >const char msg[] = "Test message";
    >
    >const char *message(void) {
    > return msg;
    >}
    >
    >int main(void){
    > const char * str;
    >
    > str = (const char *)message;
    > str = (char *)message;
    > str = message; /* GCC warning! */


    message is a pointer to a function returning const char *. The
    previous two casts are covering up a gratuitous mistake!

    Jim
    JimS, Sep 17, 2007
    #3
  4. > > str = (const char *)message;
    > > str = (char *)message;
    > > str = message; /* GCC warning! */

    >
    > message is a pointer to a function returning const char *. The
    > previous two casts are covering up a gratuitous mistake!
    >

    You are right! Silly me.

    Anyway, the compiler doesn't give any warning even if the qualifier is
    discarded by the cast:

    str = (const char *)message();
    str = (char *)message(); /* No warning! */
    str = message();

    Is this OK?

    Thanks again.

    Santi
    =?iso-8859-1?q?Santiago_Urue=F1a?=, Sep 18, 2007
    #4
  5. > Anyway, the compiler doesn't give any warning even if the qualifier is
    > discarded by the cast:
    >
    > str = (const char *)message();
    > str = (char *)message(); /* No warning! */
    > str = message();
    >
    > Is this OK?
    >

    After thinking a little more about this, I think I have the answer:
    the compiler shouldn't give a warning because a pointer to a non-const
    object is being assigned to a pointer to a const object, and this is
    totally OK because (anyway you cannot modify the object via the 'str'
    pointer).

    Thanks
    =?iso-8859-1?q?Santiago_Urue=F1a?=, Sep 18, 2007
    #5
  6. Santiago Urueña <> writes:
    >> > str = (const char *)message;
    >> > str = (char *)message;
    >> > str = message; /* GCC warning! */

    >>
    >> message is a pointer to a function returning const char *. The
    >> previous two casts are covering up a gratuitous mistake!
    >>

    > You are right! Silly me.
    >
    > Anyway, the compiler doesn't give any warning even if the qualifier is
    > discarded by the cast:
    >
    > str = (const char *)message();
    > str = (char *)message(); /* No warning! */
    > str = message();
    >
    > Is this OK?


    Please leave attribution lines in place for quoted text (i.e., lines
    like "So-and-so <> writes:"). They make it easier to
    follow the conversation, and it's just polite to credit people for
    their words.

    A cast specifies a type conversion, but what it *really* does is tell
    the compiler "I know exactly what I'm doing, don't bother me with
    warnings". Because of that property, almost all casts should be
    viewed with suspicion. Adding a cast for the sole purpose of
    silencing a compiler warning is almost always a mistake; the correct
    solution is usually to fix the code so the cast isn't required, either
    by arranging for things to be of the desired type in the first place
    or by using types that are converted implicitly.

    One of the few cases where a cast is necessary is for some arguments
    to variadic functions like printf(). For non-variadic functions, the
    compiler knows the required type and is able to generate an implicit
    conversion if necessary. For a variadic function, the compiler
    doesn't necessarily have this information, so you have to give it some
    help.

    --
    Keith Thompson (The_Other_Keith) <http://www.ghoti.net/~kst>
    San Diego Supercomputer Center <*> <http://users.sdsc.edu/~kst>
    "We must do something. This is something. Therefore, we must do this."
    -- Antony Jay and Jonathan Lynn, "Yes Minister"
    Keith Thompson, Sep 18, 2007
    #6
  7. =?iso-8859-1?q?Santiago_Urue=F1a?=

    CBFalconer Guest

    Santiago Urueña wrote:
    >
    > I tried to return a pointer to a constant string, but the compiler
    > gives the following warning if a cast is not used:
    >
    > warning: assignment from incompatible pointer type
    >
    > This is the code:
    >
    > const char msg[] = "Test message";
    >
    > const char *message(void) {
    > return msg;
    > }


    msg is an array. &msg is a pointer to msg.

    --
    Chuck F (cbfalconer at maineline dot net)
    Available for consulting/temporary embedded and systems.
    <http://cbfalconer.home.att.net>


    --
    Posted via a free Usenet account from http://www.teranews.com
    CBFalconer, Sep 18, 2007
    #7
  8. Santiago Urueña wrote:
    > Hi,
    >
    > I tried to return a pointer to a constant string, but the compiler
    > gives the following warning if a cast is not used:
    >
    > warning: assignment from incompatible pointer type
    >
    > This is the code:
    >
    >
    > const char msg[] = "Test message";
    >
    > const char *message(void) {
    > return msg;
    > }
    >
    > int main(void){
    > const char * str;
    >
    > str = (const char *)message;
    > str = (char *)message;
    > str = message; /* GCC warning! */
    >
    > str = (const char *)msg;
    > str = (char *)msg;
    > str = msg;
    >
    > return 0;
    > }


    const char msg[] = "Test message";
    /* msg (above) is a character array, but message is a function */
    const char *message(void)
    {
    return msg;
    }

    int main(void)
    {
    const char *str;
    str = message(); /* notice parenthesis; message is not a
    pointer-to-char but a function
    returning a (const) pointer-to-char */
    str = msg;
    return 0;
    }
    Martin Ambuhl, Sep 18, 2007
    #8
  9. =?iso-8859-1?q?Santiago_Urue=F1a?=

    anders Guest

    Hmm as i see it
    one type is a char [] and one is char *
    that way
    str = (char *)message();
    works.
    // Anders


    On 18 Sep, 01:49, CBFalconer <> wrote:
    > Santiago Urueña wrote:
    >
    > > I tried to return a pointer to a constant string, but the compiler
    > > gives the following warning if a cast is not used:

    >
    > > warning: assignment from incompatible pointer type

    >
    > > This is the code:

    >
    > > const char msg[] = "Test message";

    >
    > > const char *message(void) {
    > > return msg;
    > > }

    >
    > msg is an array. &msg is a pointer to msg.
    >
    > --
    > Chuck F (cbfalconer at maineline dot net)
    > Available for consulting/temporary embedded and systems.
    > <http://cbfalconer.home.att.net>
    >
    > --
    > Posted via a free Usenet account fromhttp://www.teranews.com
    anders, Sep 18, 2007
    #9
  10. "Walter Roberson" <-cnrc.gc.ca> a écrit dans le message de
    news: fcn02v$2j9$...
    > In article <>,
    > =?iso-8859-1?q?Santiago_Urue=F1a?= <> wrote:
    >
    >>I tried to return a pointer to a constant string, but the compiler
    >>gives the following warning if a cast is not used:

    >
    >> warning: assignment from incompatible pointer type

    >
    >>This is the code:

    >
    >>const char msg[] = "Test message";

    >
    >>const char *message(void) {
    >> return msg;
    >>}

    >
    > Pay close attention to the placement of the const qualifiers.
    >
    > const char msg[] says that msg[someindex] will be a const char


    correct. It could also be written char const msg[].

    > const char *message(void)
    >
    > says that message will return a pointer to a char and that the
    > pointer is constant.


    No, such a pointer would be defined as char * const p; and it makes no sense
    as a return value for a function.

    > (I think. I'm not -positive-. I haven't had much occasion to use const.)


    It shows!
    Please don't post misleading answers on subjects you know you don't master.

    --
    Chqrlie.
    Charlie Gordon, Sep 18, 2007
    #10
  11. "Santiago Urueña" <> a écrit dans le message de news:
    ...
    > Hi,
    >
    > I tried to return a pointer to a constant string, but the compiler
    > gives the following warning if a cast is not used:
    >
    > warning: assignment from incompatible pointer type
    >
    > This is the code:
    >
    >
    > const char msg[] = "Test message";
    >
    > const char *message(void) {
    > return msg;
    > }
    >
    > int main(void){
    > const char * str;
    >
    > str = (const char *)message;
    > str = (char *)message;
    > str = message; /* GCC warning! */
    >
    > str = (const char *)msg;
    > str = (char *)msg;
    > str = msg;
    >
    > return 0;
    > }
    >
    > Oddly, GCC only gives the warning if no cast is used, but it doesn't
    > complain if the cast discards the const qualifier. Is this behavior
    > OK? I'm using GCC 4.1.2. Thanks!


    Well well, gcc gives you a warning and you don't read it.
    "assignment from incompatible pointer type" is not about the const
    qualifier being discarded... after all str is a const char *, no const
    qualifier is discard by these assignments, as the rest of the code shows.

    The problem is much worse, and a good example of why casts must be avoided.
    You are attempting to store a pointer to the function 'message', not the
    result of an invocation because you missed the ().

    str = message; is correctly diagnosed as an assignment from incompatible
    pointer types.

    By casting message to (char*) or (const char*), you are effectively telling
    the compiler to shut up because you presumably know what you are doing (for
    instance, you are trying to disassemble the function and you know the
    respective representations of function pointers and char pointers are
    compatible on your target). gcc respects that and does not complain.

    But you are wrong. Your code invokes undefined behaviour.

    Consequently: do not use casts. Turn extra gcc warnings on so it complains
    about suspicious casts and a flew of other things.

    --
    Chqrlie.
    Charlie Gordon, Sep 18, 2007
    #11
  12. "CBFalconer" <> a écrit dans le message de news:
    ...
    > Santiago Urueña wrote:
    >>
    >> I tried to return a pointer to a constant string, but the compiler
    >> gives the following warning if a cast is not used:
    >>
    >> warning: assignment from incompatible pointer type
    >>
    >> This is the code:
    >>
    >> const char msg[] = "Test message";
    >>
    >> const char *message(void) {
    >> return msg;
    >> }

    >
    > msg is an array. &msg is a pointer to msg.


    But message returns a pointer to char, correctly constructed by 'return
    msg;' or 'return &msg[0];'.

    Returning &msg here would be abusing the rules.

    --
    Chqrlie.
    Charlie Gordon, Sep 18, 2007
    #12
  13. On 18 sep, 12:48, "Charlie Gordon" <> wrote:
    > "Santiago Urueña" <> a écrit dans le message de news:
    > ...
    >
    >
    >
    > > Hi,

    >
    > > I tried to return a pointer to a constant string, but the compiler
    > > gives the following warning if a cast is not used:

    >
    > > warning: assignment from incompatible pointer type

    >
    > > This is the code:

    >
    > > const char msg[] = "Test message";

    >
    > > const char *message(void) {
    > > return msg;
    > > }

    >
    > > int main(void){
    > > const char * str;

    >
    > > str = (const char *)message;
    > > str = (char *)message;
    > > str = message; /* GCC warning! */

    >
    > > str = (const char *)msg;
    > > str = (char *)msg;
    > > str = msg;

    >
    > > return 0;
    > > }

    >
    > > Oddly, GCC only gives the warning if no cast is used, but it doesn't
    > > complain if the cast discards the const qualifier. Is this behavior
    > > OK? I'm using GCC 4.1.2. Thanks!

    >
    > Well well, gcc gives you a warning and you don't read it.
    > "assignment from incompatible pointer type" is not about the const
    > qualifier being discarded... after all str is a const char *, no const
    > qualifier is discard by these assignments, as the rest of the code shows.
    >
    > The problem is much worse, and a good example of why casts must be avoided.
    > You are attempting to store a pointer to the function 'message', not the
    > result of an invocation because you missed the ().
    >
    > str = message; is correctly diagnosed as an assignment from incompatible
    > pointer types.
    >
    > By casting message to (char*) or (const char*), you are effectively telling
    > the compiler to shut up because you presumably know what you are doing (for
    > instance, you are trying to disassemble the function and you know the
    > respective representations of function pointers and char pointers are
    > compatible on your target). gcc respects that and does not complain.
    >
    > But you are wrong. Your code invokes undefined behaviour.
    >
    > Consequently: do not use casts. Turn extra gcc warnings on so it complains
    > about suspicious casts and a flew of other things.
    >

    Thank you very much for all your responses. Of course I see the
    problem now, it seems I was too asleep for not seeing that silly
    mistake.

    I always use -Wall and -Wextra until all warnings are corrected. I'm
    of those persons that believe that the compiler usually knows much
    better, I don't really know why in this case the message seemed to me
    a possible compiler bug.

    Keith, Thanks for the suggestion about variadic functions, it's always
    good to know tips like that. I don't usually use casts neither,
    specially from now on... :)

    Best regards,
    =?iso-8859-1?q?Santiago_Urue=F1a?=, Sep 18, 2007
    #13
  14. On 18 sep, 01:49, CBFalconer <> wrote:
    > Santiago Urueña wrote:
    >
    > > I tried to return a pointer to a constant string, but the compiler
    > > gives the following warning if a cast is not used:

    >
    > > warning: assignment from incompatible pointer type

    >
    > > This is the code:

    >
    > > const char msg[] = "Test message";

    >
    > > const char *message(void) {
    > > return msg;
    > > }

    >
    > msg is an array. &msg is a pointer to msg.
    >

    I'm not a language lawyer, but the & operator returns the _address_ of
    an object, not the pointer. But in this case 'msg' is directly the
    address of the array.

    I declared 'msg' as 'const char msg[] = "...";' and not as 'const char
    *const msg = "...";' because in this case there is no need to reserve
    memory for a pointer to the string, but just to the string itself.

    Best regards,

    Santi
    =?iso-8859-1?q?Santiago_Urue=F1a?=, Sep 18, 2007
    #14
  15. Santiago Urueña <> writes:
    > On 18 sep, 01:49, CBFalconer <> wrote:
    >> Santiago Urueña wrote:
    >> > I tried to return a pointer to a constant string, but the compiler
    >> > gives the following warning if a cast is not used:

    >>
    >> > warning: assignment from incompatible pointer type

    >>
    >> > This is the code:

    >>
    >> > const char msg[] = "Test message";

    >>
    >> > const char *message(void) {
    >> > return msg;
    >> > }

    >>
    >> msg is an array. &msg is a pointer to msg.
    >>

    > I'm not a language lawyer, but the & operator returns the _address_ of
    > an object, not the pointer. But in this case 'msg' is directly the
    > address of the array.


    Given an object obj, the phrases "a pointer to obj" and "the address
    of obj" are synonymous.

    Since msg is declared as an array, the expression '&msg' is the
    address *of the array*, whereas the expression 'msg' (in most
    contexts) yields the address of the arrsy's first element, the same as
    '&msg[0]'.

    [...]

    Section 6 of the comp.lang.c FAQ is an excellent resource.

    There's a program called "cdecl" that you might also find useful (if
    you can find and install it).

    --
    Keith Thompson (The_Other_Keith) <http://www.ghoti.net/~kst>
    San Diego Supercomputer Center <*> <http://users.sdsc.edu/~kst>
    "We must do something. This is something. Therefore, we must do this."
    -- Antony Jay and Jonathan Lynn, "Yes Minister"
    Keith Thompson, Sep 18, 2007
    #15
  16. =?iso-8859-1?q?Santiago_Urue=F1a?=

    Richard Guest

    Keith Thompson <> writes:

    > Santiago Urueña <> writes:
    >> On 18 sep, 01:49, CBFalconer <> wrote:
    >>> Santiago Urueña wrote:
    >>> > I tried to return a pointer to a constant string, but the compiler
    >>> > gives the following warning if a cast is not used:
    >>>
    >>> > warning: assignment from incompatible pointer type
    >>>
    >>> > This is the code:
    >>>
    >>> > const char msg[] = "Test message";
    >>>
    >>> > const char *message(void) {
    >>> > return msg;
    >>> > }
    >>>
    >>> msg is an array. &msg is a pointer to msg.
    >>>

    >> I'm not a language lawyer, but the & operator returns the _address_ of
    >> an object, not the pointer. But in this case 'msg' is directly the
    >> address of the array.

    >
    > Given an object obj, the phrases "a pointer to obj" and "the address
    > of obj" are synonymous.
    >
    > Since msg is declared as an array, the expression '&msg' is the
    > address *of the array*, whereas the expression 'msg' (in most
    > contexts) yields the address of the arrsy's first element, the same as
    > '&msg[0]'.


    I'm a bit sleepy at the moment and understand the above, but in what
    cases are &msg[0] and msg not the same in real live systems where they
    are 32 or 64 bit pointers?

    >
    > [...]
    >
    > Section 6 of the comp.lang.c FAQ is an excellent resource.
    >
    > There's a program called "cdecl" that you might also find useful (if
    > you can find and install it).
    Richard, Sep 19, 2007
    #16
  17. =?iso-8859-1?q?Santiago_Urue=F1a?=

    Eric Sosman Guest

    Richard wrote On 09/19/07 12:54,:
    > Keith Thompson <> writes:
    >> [...]
    >>Since msg is declared as an array, the expression '&msg' is the
    >>address *of the array*, whereas the expression 'msg' (in most
    >>contexts) yields the address of the arrsy's first element, the same as
    >>'&msg[0]'.

    >
    > I'm a bit sleepy at the moment and understand the above, but in what
    > cases are &msg[0] and msg not the same in real live systems where they
    > are 32 or 64 bit pointers?


    In all cases.

    An array and its [0] element begin at the same memory
    address, always, but the "address-of" an array has a
    different type than the "address-of" its [0] element.

    IMHO the Standard is unnecessarily confusing here.
    In ordinary computer jargon, an address just designates
    a memory location and says nothing about what is found
    there. A C pointer, on the other hand, also describes
    the data type that occupies the pointed-to location (and
    perhaps a few neighbors). By naming unary `&' as the
    "address-of operator" the Standard steers people toward
    the location-only mind-set, whereas unary `&' actually
    yields a full-fledged C pointer complete with type. A
    name like "pointer-to operator" would have been better.

    I'll repeat Keith's suggestion to read Section 6 of
    the FAQ, and add that Question 6.12 is exactly what you
    have asked.

    --
    Eric Sosman, Sep 19, 2007
    #17
  18. =?iso-8859-1?q?Santiago_Urue=F1a?=

    Richard Guest

    Eric Sosman <> writes:

    > Richard wrote On 09/19/07 12:54,:
    >> Keith Thompson <> writes:
    >>> [...]
    >>>Since msg is declared as an array, the expression '&msg' is the
    >>>address *of the array*, whereas the expression 'msg' (in most
    >>>contexts) yields the address of the arrsy's first element, the same as
    >>>'&msg[0]'.

    >>
    >> I'm a bit sleepy at the moment and understand the above, but in what
    >> cases are &msg[0] and msg not the same in real live systems where they
    >> are 32 or 64 bit pointers?

    >
    > In all cases.


    In what cases are the VALUES not the same. I am not talking the
    types. hence I mentioned the pointers or addresses.
    Richard, Sep 19, 2007
    #18
  19. Eric Sosman said:

    > Richard wrote On 09/19/07 12:54,:
    >> [...] in what
    >> cases are &msg[0] and msg not the same in real live systems where they
    >> are 32 or 64 bit pointers?

    >
    > In all cases.


    Not so. &msg[0] and msg are identical when their value is used in an
    expression.

    > An array and its [0] element begin at the same memory
    > address, always, but the "address-of" an array has a
    > different type than the "address-of" its [0] element.


    So you're not really talking about &msg[0] and msg, but &msg[0] and &msg.

    If the question is suitably modified, your answer becomes correct.

    <snip>

    --
    Richard Heathfield <http://www.cpax.org.uk>
    Email: -www. +rjh@
    Google users: <http://www.cpax.org.uk/prg/writings/googly.php>
    "Usenet is a strange place" - dmr 29 July 1999
    Richard Heathfield, Sep 19, 2007
    #19
  20. =?iso-8859-1?q?Santiago_Urue=F1a?=

    Eric Sosman Guest

    Richard wrote On 09/19/07 14:37,:
    > Eric Sosman <> writes:
    >
    >
    >>Richard wrote On 09/19/07 12:54,:
    >>
    >>>Keith Thompson <> writes:
    >>>
    >>>>[...]
    >>>>Since msg is declared as an array, the expression '&msg' is the
    >>>>address *of the array*, whereas the expression 'msg' (in most
    >>>>contexts) yields the address of the arrsy's first element, the same as
    >>>>'&msg[0]'.
    >>>
    >>>I'm a bit sleepy at the moment and understand the above, but in what
    >>>cases are &msg[0] and msg not the same in real live systems where they
    >>>are 32 or 64 bit pointers?

    >>
    >> In all cases.

    >
    >
    > In what cases are the VALUES not the same. I am not talking the
    > types. hence I mentioned the pointers or addresses.


    A value is the "precise meaning of the contents of an
    object when interpreted as having a specific type" (3.17).
    So if you're "not talking the types," you can't be talking
    about the values; values in C always have types.

    However, I see that I've misread your question and I
    apologize if that's created confusion. Keith wrote about
    the difference between `&msg' and `msg', the latter being
    usually the same as `&msg[0]'. You asked how `&msg[0]'
    and `msg' could be different, but with Keith's prose fresh
    in mind I managed to insert a non-existent `&' and wrote
    as if you had asked how `&msg[0]' and `&msg' could be
    different. Cue sound effect: self-administered dope slap.

    So, *now* what I think you were asking about was Keith's
    "in most contexts." There are two contexts where they could
    be different:

    When they are the operand of the sizeof operator.
    `sizeof &msg[0]' is the number of bytes in a pointer
    to an element of the array, and `sizeof msg' is the
    number of bytes in the array itself. These could be
    identical, but only by coincidence.

    When they are the operand of the unary `&' operator.
    `& &msg[0]' is a constraint violation, while `& msg'
    is a pointer to the array (different in type from a
    pointer to the array's first element, but referring
    to the same starting byte).

    Again, sorry for the mixup.

    --
    Eric Sosman, Sep 19, 2007
    #20
    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. Fraser Ross
    Replies:
    4
    Views:
    1,043
    Fraser Ross
    Aug 14, 2004
  2. Christopher M. Lusardi
    Replies:
    1
    Views:
    4,086
  3. Martin Magnusson
    Replies:
    2
    Views:
    503
    John Harrison
    Oct 8, 2004
  4. sinbad
    Replies:
    7
    Views:
    655
    sinbad
    Jun 19, 2008
  5. G G
    Replies:
    3
    Views:
    91
    Ben Bacarisse
    Apr 20, 2014
Loading...

Share This Page