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

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

P: n/a
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, su*****@uci.edu, (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 **************
Nov 14 '05 #1
Share this Question
Share on Google+
12 Replies


P: n/a
"Charlie Zender" <ze****@uci.edu> wrote in message
news:3F************@uci.edu...
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
Nov 14 '05 #2

P: n/a
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, su*****@uci.edu, (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 **************
Nov 14 '05 #3

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

Nov 14 '05 #4

P: n/a
On Fri, 02 Jan 2004 12:42:43 -0800, Charlie Zender <ze****@uci.edu>
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
Nov 14 '05 #5

P: n/a
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.
Nov 14 '05 #6

P: n/a
Charlie Zender <ze****@uci.edu> 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
Nov 14 '05 #7

P: n/a
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.
Nov 14 '05 #8

P: n/a
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, su*****@uci.edu, (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 **************
Nov 14 '05 #9

P: n/a
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.
Nov 14 '05 #10

P: n/a
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.
Nov 14 '05 #11

P: n/a
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 (cb********@yahoo.com) (cb********@worldnet.att.net)
Available for consulting/temporary embedded and systems.
<http://cbfalconer.home.att.net> USE worldnet address!
Nov 14 '05 #12

P: n/a
"CBFalconer" <cb********@yahoo.com> 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>
Nov 14 '05 #13

This discussion thread is closed

Replies have been disabled for this discussion.