By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
458,172 Members | 1,751 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 458,172 IT Pros & Developers. It's quick & easy.

Returning a pointer to a constant string

P: n/a
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

Sep 17 '07 #1
Share this Question
Share on Google+
23 Replies


P: n/a
In article <11**********************@g4g2000hsf.googlegroups. com>,
=?iso-8859-1?q?Santiago_Urue=F1a?= <su*****@gmail.comwrote:
>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
Sep 17 '07 #2

P: n/a
On Mon, 17 Sep 2007 15:38:15 -0700, Santiago Urueña
<su*****@gmail.comwrote:
>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
Sep 17 '07 #3

P: n/a
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

Sep 17 '07 #4

P: n/a
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

Sep 17 '07 #5

P: n/a
Santiago Urueña <su*****@gmail.comwrites:
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 <fo*@bar.comwrites:"). 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) ks***@mib.org <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"
Sep 17 '07 #6

P: n/a
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

Sep 17 '07 #7

P: n/a
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;
}
Sep 18 '07 #8

P: n/a
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 <cbfalco...@yahoo.comwrote:
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

Sep 18 '07 #9

P: n/a
"Walter Roberson" <ro******@ibd.nrc-cnrc.gc.caa écrit dans le message de
news: fc**********@canopus.cc.umanitoba.ca...
In article <11**********************@g4g2000hsf.googlegroups. com>,
=?iso-8859-1?q?Santiago_Urue=F1a?= <su*****@gmail.comwrote:
>>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.
Sep 18 '07 #10

P: n/a
"Santiago Urueña" <su*****@gmail.coma écrit dans le message de news:
11**********************@g4g2000hsf.googlegroups.c om...
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.
Sep 18 '07 #11

P: n/a
"CBFalconer" <cb********@yahoo.coma écrit dans le message de news:
46***************@yahoo.com...
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.
Sep 18 '07 #12

P: n/a
On 18 sep, 12:48, "Charlie Gordon" <n...@chqrlie.orgwrote:
"Santiago Urueña" <suru...@gmail.coma écrit dans le message de news:
1190068695.241389.292...@g4g2000hsf.googlegroups.c om...
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,

Sep 18 '07 #13

P: n/a
On 18 sep, 01:49, CBFalconer <cbfalco...@yahoo.comwrote:
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

Sep 18 '07 #14

P: n/a
Santiago Urueña <su*****@gmail.comwrites:
On 18 sep, 01:49, CBFalconer <cbfalco...@yahoo.comwrote:
>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) ks***@mib.org <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"
Sep 18 '07 #15

P: n/a
Keith Thompson <ks***@mib.orgwrites:
Santiago Urueña <su*****@gmail.comwrites:
>On 18 sep, 01:49, CBFalconer <cbfalco...@yahoo.comwrote:
>>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).
Sep 19 '07 #16

P: n/a
Richard wrote On 09/19/07 12:54,:
Keith Thompson <ks***@mib.orgwrites:
>[...]
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.

--
Er*********@sun.com
Sep 19 '07 #17

P: n/a
Eric Sosman <Er*********@sun.comwrites:
Richard wrote On 09/19/07 12:54,:
>Keith Thompson <ks***@mib.orgwrites:
>>[...]
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.
Sep 19 '07 #18

P: n/a
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
Sep 19 '07 #19

P: n/a
Richard wrote On 09/19/07 14:37,:
Eric Sosman <Er*********@sun.comwrites:

>>Richard wrote On 09/19/07 12:54,:
>>>Keith Thompson <ks***@mib.orgwrites:

[...]
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.

--
Er*********@sun.com
Sep 19 '07 #20

P: n/a
Richard Heathfield <rj*@see.sig.invalidwrites:
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.
When their value is used, yes, but the question was whether they're
the same in general. (The sizes of pointers are irrelevant.)

When they're the operand of a sizeof operator, their values are not
used, but they differ. Likewise for the operand of unary "&"
(but as has been pointed out, '&&msg[0]' is a constraint violation).

--
Keith Thompson (The_Other_Keith) ks***@mib.org <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"
Sep 19 '07 #21

P: n/a
Richard wrote:
>
Eric Sosman <Er*********@sun.comwrites:
Richard wrote On 09/19/07 12:54,:
Keith Thompson <ks***@mib.orgwrites:
[...]
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.
Given: const char msg[] = "Test message";
the answer to your question is that
(&msg[0] == msg) equals one, on all C implementations.
I am not talking the types.
hence I mentioned the pointers or addresses.
He was talking types.

The point he was making is that
though ((char *)&msg == (char *)msg) equals one,
(&msg == msg) is undefined.

--
pete
Sep 19 '07 #22

P: n/a
Keith Thompson said:
Richard Heathfield <rj*@see.sig.invalidwrites:
>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.

When their value is used, yes, but the question was whether they're
the same in general.
Um, no, the question was: "in what cases are &msg[0] and msg not the same
in real live systems where they are 32 or 64 bit pointers?"

Clearly the pointer-size thing is of no interest to comp.lang.c, since the
cases where &msg[0] and msg are the same or not the same is nothing to do
with pointer size as far as we're concerned. So it resolves to: "in what
cases are &msg[0] and msg not the same?" Nothing in there about "in
general". Eric's answer to this (which he acknowledges is based on a
misreading of what is probably a typo!) was "in all cases", which is
clearly not correct, because there is a case where &msg[0] and msg are the
same.
(The sizes of pointers are irrelevant.)
Agreed.
When they're the operand of a sizeof operator, their values are not
used, but they differ. Likewise for the operand of unary "&"
(but as has been pointed out, '&&msg[0]' is a constraint violation).
Yes, there are indeed cases where they differ, but "in some cases" != "in
all cases".

--
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
Sep 20 '07 #23

P: n/a
Richard Heathfield <rj*@see.sig.invalidwrites:
Keith Thompson said:
>Richard Heathfield <rj*@see.sig.invalidwrites:
>>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.

When their value is used, yes, but the question was whether they're
the same in general.

Um, no, the question was: "in what cases are &msg[0] and msg not the same
in real live systems where they are 32 or 64 bit pointers?"
Sorry, I misunderstood your correction to be more general that it
obviously was. (I should spend more time reading and thinking when
something you post looks wrong; it happens, but it's not the way to
bet.)

--
Keith Thompson (The_Other_Keith) ks***@mib.org <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"
Sep 20 '07 #24

This discussion thread is closed

Replies have been disabled for this discussion.