Best way of clearing a compiler warning?

D

Daniel Rudy

Hello,

Consider the following code fragment:

fileptr = fopen(param->filename, "r");
if (fileptr == NULL)
{
error("digest.c: digest_file: Open File ", errno);
return(-2);
}

With the above code, the compiler (gcc) gives the following warning:

digest.c:121: warning: passing arg 1 of `error' discards qualifiers from
pointer target type.

The function error is declared as follows:

void error(char *errmsg, int code);

Why does it give this message and how do I silence it?

Thanks

--
Daniel Rudy

Email address has been base64 encoded to reduce spam
Decode email address using b64decode or uudecode -m

Why geeks like computers: look chat date touch grep make unzip
strip view finger mount fcsk more fcsk yes spray umount sleep
 
S

Skarmander

Daniel said:
Consider the following code fragment:

fileptr = fopen(param->filename, "r");
if (fileptr == NULL)
{
error("digest.c: digest_file: Open File ", errno);
return(-2);
}

With the above code, the compiler (gcc) gives the following warning:

digest.c:121: warning: passing arg 1 of `error' discards qualifiers from
pointer target type.

The function error is declared as follows:

void error(char *errmsg, int code);

Why does it give this message

Because you're passing a string literal, which is const. `error' is
declared as taking a char*, meaning it does not promise not to modify
the contents of its argument. If it does, Bad Things will happen.
and how do I silence it?
If `error' really doesn't modify `errmsg', change the prototype and the
function to take a const char* instead.

If it does modify `errmsg', you'll have to copy the message to a newly
allocated string.

S.
 
D

Daniel Rudy

At about the time of 11/6/2005 4:59 PM, Skarmander stated the following:
Because you're passing a string literal, which is const. `error' is
declared as taking a char*, meaning it does not promise not to modify
the contents of its argument. If it does, Bad Things will happen.

I see. error does not modify the contents of *errmsg, just prints it
out using either syslog or fprintf to stderr.
If `error' really doesn't modify `errmsg', change the prototype and the
function to take a const char* instead.

If it does modify `errmsg', you'll have to copy the message to a newly
allocated string.

S.

Ah, thanks.

--
Daniel Rudy

Email address has been base64 encoded to reduce spam
Decode email address using b64decode or uudecode -m

Why geeks like computers: look chat date touch grep make unzip
strip view finger mount fcsk more fcsk yes spray umount sleep
 
B

Ben Pfaff

Skarmander said:
Because you're passing a string literal, which is const.

No, you're wrong. String literals are not const in C. Here is a
quote from C99 section 6.4.5 "String Literals":

The multibyte character sequence is then used to initialize
an array of static storage duration and length just
sufficient to contain the sequence. For character string
literals, the array elements have type char, and are
initialized with the individual bytes of the multibyte
character sequence; [...]
`error' is declared as taking a char*, meaning it does not
promise not to modify the contents of its argument. If it does,
Bad Things will happen.

String literals are definitely unmodifiable. Continuing the
quote:

If the program attempts to modify such an array, the
behavior is undefined.

It is more likely that the OP is using the GCC option described
in the following quote from GCC's manual:

`-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.

GCC is not a C compiler when -Wwrite-strings is used. Instead,
it compiles a similar languages where string literals have type
const char[]. (It is very deceptive to make a -W warning option
change the language compiled.)
 
D

Daniel Rudy

At about the time of 11/6/2005 5:08 PM, pete stated the following:
A string literal isn't const qualified.

Even so, it seems to have corrected the problem. I don't get the
warning anymore.

--
Daniel Rudy

Email address has been base64 encoded to reduce spam
Decode email address using b64decode or uudecode -m

Why geeks like computers: look chat date touch grep make unzip
strip view finger mount fcsk more fcsk yes spray umount sleep
 
S

Skarmander

Daniel said:
At about the time of 11/6/2005 5:08 PM, pete stated the following:




Even so, it seems to have corrected the problem. I don't get the
warning anymore.

Yes. I gave you the right answer for the wrong reason.

S.
 
K

Keith Thompson

Daniel Rudy said:
Consider the following code fragment:

fileptr = fopen(param->filename, "r");
if (fileptr == NULL)
{
error("digest.c: digest_file: Open File ", errno);
return(-2);
}

With the above code, the compiler (gcc) gives the following warning:

digest.c:121: warning: passing arg 1 of `error' discards qualifiers from
pointer target type.

The function error is declared as follows:

void error(char *errmsg, int code);

Why does it give this message and how do I silence it?

The message implies that gcc thinks the argument is of type "const
char*". In fact, C string literals are of type "array of char"
(decaying to char*); modifying an element of a string literal doesn't
violate "const", but it does invoke undefined behavior.

gcc has an option to warn about attempts to modify string literals,
but it's implemented by pretending that string literals are const,
which would trigger the warning you're seeing. (Also, string literals
are const in C++; are you sure you're invoking gcc as a C compiler?)

One fix would be to cast the argument to char*:

error((char*)"digest.c: digest_file: Open File ", errno);

A better fix would be to modify the declaration of error() to:

void error(const char *errmsg, int code);

Presumably error() doesn't need to modify its argument anyway, so this
is a better description of what it does.
 
S

Skarmander

Ben said:
No, you're wrong. String literals are not const in C. Here is a
quote from C99 section 6.4.5 "String Literals":
<snip>

My bad. Is anyone surprised that they are const in C++, and that I've
gotten rather used to this?

And, of course, you're supposed to act as *if* they're const in C, or
undefined behavior will be your punishment. For hysterical reasons, etc.

S.
 
K

Keith Thompson

Ben Pfaff said:
It is more likely that the OP is using the GCC option described
in the following quote from GCC's manual:

`-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.

GCC is not a C compiler when -Wwrite-strings is used. Instead,
it compiles a similar languages where string literals have type
const char[]. (It is very deceptive to make a -W warning option
change the language compiled.)

The "-Wwrite-strings" option causes gcc to emit warnings when it
otherwise wouldn't. Since an implementation is allowed to issue
whatever spurious diagnostics it likes, that doesn't necessarily make
it non-conforming.

It would be better if the option did what its name implies -- i.e.,
cause gcc to issue warnings for attempts to modify string literals
without changing their type. Making them const is a quick and dirty
way to accomplish this; it has the unfortunate side effect of
producing *inaccurate* warnings, but the standard doesn't actually
require warnings to be accurate.
 
S

Skarmander

Ben Pfaff wrote:
`-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.

GCC is not a C compiler when -Wwrite-strings is used. Instead,
it compiles a similar languages where string literals have type
const char[]. (It is very deceptive to make a -W warning option
change the language compiled.)

gcc is still a C compiler with -Wwrite-strings, since the resulting code
is semantically equivalent to code where string literals are not
const, including undefined behavior for modifying literals. "An
implementation is free to produce any number of diagnostics as long as a
valid program is still correctly translated." This will be the case even
if -Wwrite-strings is used; the compiler is just generating diagnostics
when the standard doesn't require it to.

If gcc miscompiled (or refused to compile) valid code with
-Wwrite-strings, it would be another matter, but I don't think that can
happen. At worst you get extra diagnostics.

S.
 
D

Daniel Rudy

At about the time of 11/6/2005 5:11 PM, Ben Pfaff stated the following:
Because you're passing a string literal, which is const.


No, you're wrong. String literals are not const in C. Here is a
quote from C99 section 6.4.5 "String Literals":

The multibyte character sequence is then used to initialize
an array of static storage duration and length just
sufficient to contain the sequence. For character string
literals, the array elements have type char, and are
initialized with the individual bytes of the multibyte
character sequence; [...]

`error' is declared as taking a char*, meaning it does not
promise not to modify the contents of its argument. If it does,
Bad Things will happen.

I don't _intentionally_ try to modify string literals or constants for
that matter in my programs. Accedentially now, may be another story...
String literals are definitely unmodifiable. Continuing the
quote:

If the program attempts to modify such an array, the
behavior is undefined.

Which is pretty much the same thing with a const.
It is more likely that the OP is using the GCC option described
in the following quote from GCC's manual:

`-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.

GCC is not a C compiler when -Wwrite-strings is used. Instead,
it compiles a similar languages where string literals have type
const char[]. (It is very deceptive to make a -W warning option
change the language compiled.)

Here's my command line:

gcc -W -Wall -Wshadow -Wpointer-arith -Wcast-align -Wstrict-prototypes
-Wmissing-prototypes -Wnested-externs -Wwrite-strings -Wfloat-equal
-Winline -Wtrigraphs -pedantic -ansi -std=c89 -ggdb3 -I.. -lm -lmd -lc
-lcrypto -o digest.test digest.test.c digest.c ../sha2.c ../error.c
.../syslog.c

--
Daniel Rudy

Email address has been base64 encoded to reduce spam
Decode email address using b64decode or uudecode -m

Why geeks like computers: look chat date touch grep make unzip
strip view finger mount fcsk more fcsk yes spray umount sleep
 
B

Ben Pfaff

Daniel Rudy said:
At about the time of 11/6/2005 5:11 PM, Ben Pfaff stated the following:

Which is pretty much the same thing with a const.

The effect of attempting to modify a string literal is the same
as attempting to modify a const object: both yield undefined
behavior. But a string literal is not actually const qualified.
It is more likely that the OP is using the GCC option described
in the following quote from GCC's manual:

`-Wwrite-strings'
[...]

Here's my command line:

gcc -W -Wall -Wshadow -Wpointer-arith -Wcast-align -Wstrict-prototypes
-Wmissing-prototypes -Wnested-externs -Wwrite-strings -Wfloat-equal
^^^^^^^^^^^^^^^
There you go. If you remove that, your original code should
compile free of that particular warning.
 
A

August Karlstrom

Daniel said:
Hello,

Consider the following code fragment:

fileptr = fopen(param->filename, "r");
if (fileptr == NULL)
{
error("digest.c: digest_file: Open File ", errno);

Where is `error' declared? As far as I know, It's not in the standard
library.


August
 
K

Keith Thompson

Ben Pfaff said:
^^^^^^^^^^^^^^^
There you go. If you remove that, your original code should
compile free of that particular warning.

Yes, but it's a good warning.

Here's an inexact summary of the code in question:

void error(char *errmsg, int code);
....
error("This is an error message", errno);

Given this, the compiler can't tell whether error() modifies the
string passed to it. If it could analyze the actual implementation of
the error() function, it could safely refrain from warning about the
use of a string literal.

The best way to handle this is for the error() function to promise not
to modify the string that its argument points to; the compiler than
then warn about calls that might potentially violate that promise.
 
L

lawrence.jones

Skarmander said:
And, of course, you're supposed to act as *if* they're const in C, or
undefined behavior will be your punishment. For hysterical reasons, etc.

You misspelled "hysterical raisins".

-Larry Jones

Let's just sit here a moment... and savor the impending terror. -- Calvin
 
D

Daniel Rudy

At about the time of 11/6/2005 8:00 PM, August Karlstrom stated the
following:
Where is `error' declared? As far as I know, It's not in the standard
library.


August

Because it's not a standard function. It's one that I wrote to help
simplify error handling for my programs.

--
Daniel Rudy

Email address has been base64 encoded to reduce spam
Decode email address using b64decode or uudecode -m

Why geeks like computers: look chat date touch grep make unzip
strip view finger mount fcsk more fcsk yes spray umount sleep
 
A

August Karlstrom

Daniel said:
At about the time of 11/6/2005 8:00 PM, August Karlstrom stated the
following:



Because it's not a standard function. It's one that I wrote to help
simplify error handling for my programs.

Yes, of course. When I reread your post it all makes sense. Sorry.


August
 
M

Michael Wojcik

Ben Pfaff said:
`-Wwrite-strings'
When compiling C, give string constants the type `const
char[LENGTH]' ...

GCC is not a C compiler when -Wwrite-strings is used. Instead,
it compiles a similar languages where string literals have type
const char[].

The "-Wwrite-strings" option causes gcc to emit warnings when it
otherwise wouldn't. Since an implementation is allowed to issue
whatever spurious diagnostics it likes, that doesn't necessarily make
it non-conforming.

No, but if the documentation is accurate, and -Wwrite-strings changes
the type of character literals, that *does* make it non-conforming.
It would be better if the option did what its name implies -- i.e.,
cause gcc to issue warnings for attempts to modify string literals
without changing their type.

Yes, as that would be conforming.

--
Michael Wojcik (e-mail address removed)

Some there are, brave, high-souled fellows, who could borrow the world to
play at ball, and never feel the responsibility, whereas others are uneasy
and not themselves with a single shilling that does not belong to them.
-- Arthur Ransome
 

Ask a Question

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

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,776
Messages
2,569,603
Members
45,201
Latest member
KourtneyBe

Latest Threads

Top