Warning meaning.


M

mdh

Hi All,
Happy Solstice!
May I ask the following.

The following is a brief excerpt of a practice program.

main(...){
if (argc > 1 && mystrcomp(argv[1], "-n") == 0) /* argv is "-n" /
******/
.......}

int mystrcomp( char *s, char *t){....}

I get the following warning related to the line marked by asterisks.
"Warning:passing argument 1 of 'strcomp' discards qualifiers from
pointer target type."

I am sure I will have some more questions, but what exactly does this
warning mean?

thanks, in advance.
 
Ad

Advertisements

R

Richard Heathfield

mdh said:
Hi All,
Happy Solstice!

<grump>
We do April Fool's Day, and that's it. No solstices, no ramadans, no
christmases, no divalis, no nuffink. Just 1 April (or April 1, on some
planets).
May I ask the following.

The following is a brief excerpt of a practice program.

main(...){
if (argc > 1 && mystrcomp(argv[1], "-n") == 0) /* argv is "-n" /
******/
......}

int mystrcomp( char *s, char *t){....}

I get the following warning related to the line marked by asterisks.
"Warning:passing argument 1 of 'strcomp' discards qualifiers from
pointer target type."

I am sure I will have some more questions, but what exactly does this
warning mean?

It means your compiler is lying to you, by pretending that string
literals are const, rather than merely constant.

Nevertheless, if all you're doing is comparing strings, it will do you
no harm to make those pointers const:

int mystrcomp(const char *s, const char *t)

and as a pleasant side-effect, that spurious warning should vanish into
the mist.
 
K

Keith Thompson

mdh said:
The following is a brief excerpt of a practice program.

main(...){
if (argc > 1 && mystrcomp(argv[1], "-n") == 0) /* argv is "-n" /
******/
......}

int mystrcomp( char *s, char *t){....}

I get the following warning related to the line marked by asterisks.
"Warning:passing argument 1 of 'strcomp' discards qualifiers from
pointer target type."

I am sure I will have some more questions, but what exactly does this
warning mean?

This is a very good illustration of why we ask people to post *exact*
code and error messages (copy-and-paste, don't re-type).

Your error message refers to a function "strcomp", but your code
declares and calls a function called "mystrcomp". I could guess that
it's just a typo, but if you had copy-and-pasted your actual code I
wouldn't have to guess.

Assuming that "strcomp" is really "mystrcomp", your compiler is
complaining about the first argument, which is argv[1]. Assuming that
argv is the usual parameter to main (we can't be certain of that
either), you have to declare it yourself -- right where you've written
"main(...)".

Is a declaration for your mystrcomp() function visible at the point
where you've called it?

Reduce your program to a smaller *complete* version that exhibits the
same problem. Give us something we can try ourselves.
 
M

mdh

........
</grump>

Sorry...no offense meant.

main(...){
if (argc > 1 && mystrcomp(argv[1], "-n") == 0) /* argv is "-n" /
******/
......}
int mystrcomp( char *s, char *t){....}
I get the following warning related to the line marked by asterisks.
"Warning:passing argument 1 of 'strcomp' discards qualifiers from
pointer target type."
It means your compiler is lying to you, by pretending that string
literals are const, rather than merely constant.


Richard...from our previous discussions, I thought a string literal
like "hello world" was a constant? Could you explain a little further
what you mean by "> literals are const, rather than merely constant."

Nevertheless, if all you're doing is comparing strings, it will do you
no harm to make those pointers const:

int mystrcomp(const char *s, const char *t)

and as a pleasant side-effect, that spurious warning should vanish into
the mist.

.....which is exactly what happened.
 
M

mdh

mdh said:
The following is a brief excerpt of a practice program.
main(...){
if (argc > 1 && mystrcomp(argv[1], "-n") == 0) /* argv is "-n" /
******/
......}
int mystrcomp( char *s, char *t){....}


This is a very good illustration of why we ask people to post *exact*
code and error messages (copy-and-paste, don't re-type).

Your error message refers to a function "strcomp", but your code
declares and calls a function called "mystrcomp". I could guess that
it's just a typo,

Indeed it was...apologies..it is rather late here and I am on
call...so not at my best.


Reduce your program to a smaller *complete* version that exhibits the
same problem. Give us something we can try ourselves.

Ok...I was trying to navigate the road between " just the program
please, not all the extraneous stuff " and "not enough" ...but I get
your point. :) Next time I will be clearer.
 
M

mdh

Sorry, Keith. I am quite novel at this..but with all the polishing I
am getting from the clc, I am sure I will start to shine in a few
years!!!!
..........snip......

This is a very good illustration of why we ask people to post *exact*
code and error messages (copy-and-paste, don't re-type).

Is a declaration for your mystrcomp() function visible at the point
where you've called it?

I believe so...see below.
Reduce your program to a smaller *complete* version that exhibits the
same problem. Give us something we can try ourselves.

-

#include <stdio.h>
#define MAXLINES 10
int strcomp( char *, char *);

int main (int argc, const char * argv[]) {
int numerics=0;
if (argc > 1 && strcomp(argv[1], "-n") == 0)
numerics=1;
/* warning: passing argument 1 of 'strcomp' discards qualifiers from
pointer target type*/

return 0;
}


int strcomp( char *s, char *t){
for ( ; *s == *t; s++, t++)
if ( *s == '\0')
return 0;
return *s - *t;
}
 
Ad

Advertisements

R

Richard Heathfield

mdh said:
Sorry...no offense meant.

Oh, don't worry - I'm not offended, just grumpy. :)

Richard...from our previous discussions, I thought a string literal
like "hello world" was a constant?

Yes. It is an array of 12 char, with static storage duration, and we're
not *allowed* to write to it, which is why we call it constant, but it
is *not* const. An analogy for you: we're not *allowed* to mug little
old ladies in the street. But if we *do*, we'll probably get away with
it, more's the pity. Nevertheless, we still ought not to mug little old
ladies, and we still ought not write to string literals. And just as we
*might* get caught by the police, so we *might* have our program
explode in our faces because the implementation wrote the string
literal into read-only memory or because it merged duplicate string
literals.

<snip>
 
R

Richard Heathfield

mdh said:

int main (int argc, const char * argv[]) {

See pete's comment elsethread.
int strcomp( char *s, char *t){

strcomp invades implementation namespace. These alternatives do not:

mystrcomp
str_comp
compstr

Furthermore, const char *s and const char *t would be an improvement, as
I believe you have already discovered (possibly after posting the
above).
for ( ; *s == *t; s++, t++)
if ( *s == '\0')
return 0;
return *s - *t;

In general terms, it's more robust to do this in terms of relational
expressions rather than arithmetic. For example:

return (*s > *t) - (*s < *t);
 
A

Army1987

mdh said:
Sorry, Keith. I am quite novel at this..but with all the polishing I
am getting from the clc, I am sure I will start to shine in a few
years!!!!
.........snip......

This is a very good illustration of why we ask people to post *exact*
code and error messages (copy-and-paste, don't re-type).

Is a declaration for your mystrcomp() function visible at the point
where you've called it?

I believe so...see below.
Reduce your program to a smaller *complete* version that exhibits the
same problem. Give us something we can try ourselves.

-

#include <stdio.h>
#define MAXLINES 10
int strcomp( char *, char *);

int main (int argc, const char * argv[]) {
int numerics=0;
if (argc > 1 && strcomp(argv[1], "-n") == 0)
numerics=1;
/* warning: passing argument 1 of 'strcomp' discards qualifiers from
pointer target type*/

Passing argv[1] which is a const char* to strcomp which wants a
char* discards the const qualifier. How could the warning be
clearer?
(And I'm not sure if the second argument of main can be const, but
I feel too lazy to check the standard right now, so for now I
suggest to declare it without const.)
 
M

mdh

Yes. It is an array of 12 char, with static storage duration, and we're
not *allowed* to write to it, which is why we call it constant, but it
is *not* const.

Just out of curiosity, is this memory actually in some area which is
designated "read-only" or is it any old memory which the compiler
decides is to be read-only until it is made read/write again?
............ wrote the string
literal into read-only memory or because it merged duplicate string
literals.

So, if I understand you correctly, in the function definition
( understanding that it should have different name) the term "constant
char * implies that the pointer (to the char array) being passed
should point to a static area of memory?
 
Ad

Advertisements

M

mdh

mdh said:
int main (int argc, const char * argv[])

There's your problem. Should be:

int main(int argc, char *argv[])

instead.

Thank you Pete..
I am beginning to understand the difference in terms of "type of
memory"..(.as per RH.) ..for a char array.
 
M

mdh

In general terms, it's more robust to do this in terms of relational
expressions rather than arithmetic. For example:

return (*s > *t) - (*s < *t);


Thanks ...never seen it that way...but it is quite elegant.
 
R

Richard Bos

mdh said:
Just out of curiosity, is this memory actually in some area which is
designated "read-only" or is it any old memory which the compiler
decides is to be read-only until it is made read/write again?

Depends entirely on the implementation. On an embedded device it may
well be cost-effective to burn string literals into ROM. Some compilers
for home computers may not even bother actually making it read-only.

Richard
 
E

Eric Sosman

Richard said:
mdh said:
The following is a brief excerpt of a practice program.

main(...){
if (argc > 1 && mystrcomp(argv[1], "-n") == 0) /* argv is "-n" /
******/
......}

int mystrcomp( char *s, char *t){....}

I get the following warning related to the line marked by asterisks.
"Warning:passing argument 1 of 'strcomp' discards qualifiers from
pointer target type."

I am sure I will have some more questions, but what exactly does this
warning mean?

It means your compiler is lying to you, by pretending that string
literals are const, rather than merely constant.

Hard to be sure, but I don't think that's the issue.
The message refers to argument 1, argv[1], not to the
string literal that is argument 2. (Of course, the message
also refers to strcomp and not to mystrcomp, so we know
the facts have been fudged a little ...)

It would be helpful to see the whole program, or at
least the true nature of `...' in `main(...)'.
Nevertheless, if all you're doing is comparing strings, it will do you
no harm to make those pointers const:

int mystrcomp(const char *s, const char *t)

Yes, that's a good idea in any case.
 
R

Richard Heathfield

mdh said:
Just out of curiosity, is this memory actually in some area which is
designated "read-only" or is it any old memory which the compiler
decides is to be read-only until it is made read/write again?

It depends on the implementation. There's nothing to stop an
implementation from writing read-only data to an EPROM, for example.
So, if I understand you correctly, in the function definition
( understanding that it should have different name) the term "constant
char * implies that the pointer (to the char array) being passed
should point to a static area of memory?

No, I don't know where you got that from. All I'm saying is "don't
modify string literals". The const char * is a promise that the
function won't write through that pointer - i.e. won't change the
string that is passed to it.
 
Ad

Advertisements

M

mdh

mdh said:


No, I don't know where you got that from. All I'm saying is "don't
modify string literals". The const char * is a promise that the
function won't write through that pointer - i.e. won't change the
string that is passed to it.

Ok...I now I see what you mean. Thank you.
 
C

CBFalconer

Richard said:
.... snip ...


Depends entirely on the implementation. On an embedded device it
may well be cost-effective to burn string literals into ROM. Some
compilers for home computers may not even bother actually making
it read-only.

[OT] If you are using gcc, try:

"-W -Wall -ansi -pedantic -Wwrite-strings"

as flags to catch things early. [/OT]
 
Ad

Advertisements

C

CBFalconer

mdh said:
.... snip ...


Thanks ...never seen it that way...but it is quite elegant.

Since it never deals with numbers greater than 1, it avoids all
possibilities of overflow. Also works for all numerical types for
*s and *t.
 

Top