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

Warning when comparing char[] to a #define'd string

P: n/a
Hi,

let's say I have this:

#include <string.h>

#define BLAH "foo"

Later on, I do this:

unsigned char yadda [10];

/* ... get a couple of bytes ( = string) from buffer ... */

if (strcmp (BLAH, yadda) == 0) { printf ("yeehaw!\n"); }

This gives me the following warning:
warning: pointer targets in passing argument 1 of 'strcmp' differ in
signedness
I'm asking because I do not know about signed or unsigned in _quoted_
#define's.
Also several attempts of casting the stuff (both arg#1 + arg#2) failed.
Seems to be a gcc 4-only default to check this.
(I bet this was there in gcc3 also, it was just not enabled by default)

Thanks,
Andreas

Nov 7 '08 #1
Share this Question
Share on Google+
13 Replies


P: n/a
Andreas Eibach wrote:
let's say I have this:

#include <string.h>

#define BLAH "foo"

Later on, I do this:

unsigned char yadda [10];

/* ... get a couple of bytes ( = string) from buffer ... */

if (strcmp (BLAH, yadda) == 0) { printf ("yeehaw!\n"); }
This is no different from:

#include <string.h>

unsigned char yadda [10];

/* ... get a couple of bytes ( = string) from buffer ... */

if (strcmp ("foo", yadda) == 0) { printf ("yeehaw!\n"); }
This gives me the following warning:
warning: pointer targets in passing argument 1 of 'strcmp' differ in
signedness
You're comparing a (char *) and an (unsigned char *). The warning makes
sense. If yadda contains a string, it should be a char[], not an
unsigned char[].
I'm asking because I do not know about signed or unsigned in _quoted_
#define's.
The #define is irrelevant. See the simplification above.
Also several attempts of casting the stuff (both arg#1 + arg#2) failed.
Casting "foo" to (unsigned char *) or casting yadda to (char *) should
mask the warning, but the better solution is to use the correct types.
Seems to be a gcc 4-only default to check this.
(I bet this was there in gcc3 also, it was just not enabled by default)
Possibly; ask the GCC folks.

char might be unsigned on your system, but even so "char" and "unsigned
char" aren't exactly the same thing. It's not like "int" and "signed
int" being the same.

S
Nov 7 '08 #2

P: n/a

"Stephen Sprunk" <st*****@sprunk.orgwrote:
You're comparing a (char *) and an (unsigned char *). The warning makes
sense. If yadda contains a string, it should be a char[], not an
unsigned char[].
I'm asking because I do not know about signed or unsigned in _quoted_
#define's.

The #define is irrelevant. See the simplification above.
OK.
Also several attempts of casting the stuff (both arg#1 + arg#2) failed.

Casting "foo" to (unsigned char *) or casting yadda to (char *) should
mask the warning, but the better solution is to use the correct types.
Thanks for the tip - I did a few tests with modified code.
Three variations tested, two of them work, with one of the latter needing an
additional malloc().

Now it comes : :))

[variation #1+#2]

#include <string.h>

#define BLAH "foo"
char * yadda; /* variation #2: char yadda[10]; */

....malloc ()... /* for variation #2: do not use */

/* ... get a couple of bytes ( = string) from buffer ...*/

if (strcmp (BLAH, yadda) == 0) { printf ("yeehaw!\n"); }

both WORK!

BUT

[variation #3]
#include <string.h>

#define BLAH (unsigned char*) "foo"
....
unsigned char yadda[10]; /* unsigned char* ^= unsigned char[] */

/* ... get a couple of bytes ( = string) from buffer ... */
if (strcmp (BLAH, yadda) == 0) { printf ("yeehaw!\n"); }

gives me even TWO warnings!

So I will stick to using _signed_ char* in the strcmp(), even though I'm not
needing negative values.
Looks like strcmp() does not accept unsigned char*, even though both
arguments are now of same type.
Seems to be a gcc 4-only default to check this.
(I bet this was there in gcc3 also, it was just not enabled by default)

Possibly; ask the GCC folks.
Could be a good idea.
Thanks for the reply,

-Andreas

Nov 7 '08 #3

P: n/a
Stephen Sprunk wrote, On 07/11/08 17:52:
Andreas Eibach wrote:
>let's say I have this:

#include <string.h>

#define BLAH "foo"

Later on, I do this:

unsigned char yadda [10];

/* ... get a couple of bytes ( = string) from buffer ... */

if (strcmp (BLAH, yadda) == 0) { printf ("yeehaw!\n"); }
<snip>
>This gives me the following warning:
warning: pointer targets in passing argument 1 of 'strcmp' differ in
signedness

You're comparing a (char *) and an (unsigned char *). The warning makes
sense. If yadda contains a string, it should be a char[], not an
unsigned char[].
No he isn't, he is passing both to a function that expects to pointers
to char (not unsigned or signed but plain) which happens to do a comparison.
>I'm asking because I do not know about signed or unsigned in _quoted_
#define's.

The #define is irrelevant. See the simplification above.
>Also several attempts of casting the stuff (both arg#1 + arg#2) failed.

Casting "foo" to (unsigned char *) or casting yadda to (char *) should
mask the warning, but the better solution is to use the correct types.
Casting the string literal will just make matters worse because then it
will be two pointers which don't match in signedness instead of just one.
>Seems to be a gcc 4-only default to check this.
(I bet this was there in gcc3 also, it was just not enabled by default)

Possibly; ask the GCC folks.
It isn't enabled by default on my machine with gcc 4.3.2. It is enabled
if I specify -ansi -pedantic, which is correct as a diagnostic is required.
char might be unsigned on your system, but even so "char" and "unsigned
char" aren't exactly the same thing. It's not like "int" and "signed
int" being the same.
Casting yadda to char* removes the warning on my machine, but I would
seriously consider whether it should be plain char.
--
Flash Gordon
If spamming me sent it to sm**@spam.causeway.com
If emailing me use my reply-to address
See the comp.lang.c Wiki hosted by me at http://clc-wiki.net/
Nov 7 '08 #4

P: n/a
Andreas Eibach wrote, On 07/11/08 19:10:
"Stephen Sprunk" <st*****@sprunk.orgwrote:
<snip>
/* ... get a couple of bytes ( = string) from buffer ... */
if (strcmp (BLAH, yadda) == 0) { printf ("yeehaw!\n"); }

gives me even TWO warnings!
See my other reply.
So I will stick to using _signed_ char* in the strcmp(), even though I'm not
needing negative values.
Plain char is NOT signed char. On some systems it happens to be signed,
on some it is unsigned, but it is ALWAYS a distinct type from both.

Always use plain char for character data *unless* there is a specific
good reason to use something else.
Looks like strcmp() does not accept unsigned char*, even though both
arguments are now of same type.
<snip>

See my other reply.
--
Flash Gordon
If spamming me sent it to sm**@spam.causeway.com
If emailing me use my reply-to address
See the comp.lang.c Wiki hosted by me at http://clc-wiki.net/
Nov 7 '08 #5

P: n/a
Andreas Eibach wrote:
Hi,

let's say I have this:

#include <string.h>

#define BLAH "foo"

Later on, I do this:

unsigned char yadda [10];

/* ... get a couple of bytes ( = string) from buffer ... */

if (strcmp (BLAH, yadda) == 0) { printf ("yeehaw!\n"); }

This gives me the following warning:
warning: pointer targets in passing argument 1 of 'strcmp' differ in
signedness
Are you sure the error message matches the code you have shown?
If so, report the bug[*] to your compiler vendor. (Or upgrade to a
newer version. For what it's worth, your code elicits a warning from
gcc 4.3.2, but with that version the warning is correct.)
[*] Technically speaking it isn't a bug, because a compiler is
allowed to issue any diagnostic messages it cares to, even if those
messages are incorrect. Nonetheless, I think the maintainers of
the compiler in question would consider this behavior a bug, and
would thank you for reporting it.

--
Er*********@sun.com
Nov 7 '08 #6

P: n/a
Andreas Eibach wrote:
>
.... snip ...
>
So I will stick to using _signed_ char* in the strcmp(), even
though I'm not needing negative values. Looks like strcmp()
does not accept unsigned char*, even though both arguments are
now of same type.
No. You should recognize that there are three distinct types of
chars in C. char, signed char, and unsigned char. They are
distinct. For any implemented C system char has been set to be one
of signed char, or unsigned char. You don't necessarily know
which. What you do know is that strings are represented by arrays
of char (with a '\0' terminator), and are passed as pointers to
char (char*).

It looks as if your system has char set to be signed char. Don't
assume this in general.

--
[mail]: Chuck F (cbfalconer at maineline dot net)
[page]: <http://cbfalconer.home.att.net>
Try the download section.
Nov 8 '08 #7

P: n/a
Andreas Eibach wrote:
"Stephen Sprunk" <st*****@sprunk.orgwrote:
>>Also several attempts of casting the stuff (both arg#1 + arg#2) failed.

Casting "foo" to (unsigned char *) or casting yadda to (char *) should
mask the warning, but the better solution is to use the correct types.

Thanks for the tip - I did a few tests with modified code.
Three variations tested, two of them work, with one of the latter needing an
additional malloc().

Now it comes : :))

[variation #1+#2]

#include <string.h>

#define BLAH "foo"
char * yadda; /* variation #2: char yadda[10]; */

...malloc ()... /* for variation #2: do not use */

/* ... get a couple of bytes ( = string) from buffer ...*/

if (strcmp (BLAH, yadda) == 0) { printf ("yeehaw!\n"); }

both WORK!
They work because they're correct.
BUT

[variation #3]
#include <string.h>

#define BLAH (unsigned char*) "foo"
...
unsigned char yadda[10]; /* unsigned char* ^= unsigned char[] */

/* ... get a couple of bytes ( = string) from buffer ... */
if (strcmp (BLAH, yadda) == 0) { printf ("yeehaw!\n"); }

gives me even TWO warnings!
What warnings? I presume you mean the original warning about comparing
strings with different signed-ness is gone and there are two new ones
about passing (unsigned char *)s to a function expecting (char *)s?

If I saw this code, I'd warn you, too. (unsigned char *) is not the
right type to be using with strings. It'll probably work, but it
misleads the reader as to what's going on.
So I will stick to using _signed_ char* in the strcmp(), even though I'm not
needing negative values.
No, do not use (signed char *). When working with strings, always use
(char *). Even if (char) happens to be signed on your system, it is
still a distinct type from (signed char).
Looks like strcmp() does not accept unsigned char*, even though both
arguments are now of same type.
strcmp() is specified to take two arguments of type (char *). If you
pass in (signed char *) _or_ (unsigned char *), it's not surprising that
your compiler warns you about using the wrong type. When working with
strings, always use (char *).

S
Nov 8 '08 #8

P: n/a

"Flash Gordon" <sm**@spam.causeway.comschrieb:
Casting "foo" to (unsigned char *) or casting yadda to (char *) should
mask the warning, but the better solution is to use the correct types.

Casting the string literal will just make matters worse because then it
will be two pointers which don't match in signedness instead of just one.
True. I was just trying to keep it short :) but I also did try this 4th
variation.
And of course, I got 2 warnings about non-respected signedness.
char might be unsigned on your system, but even so "char" and "unsigned
char" aren't exactly the same thing. It's not like "int" and "signed
int" being the same.

Yes, I agree I had confused and set this equal to (un)signed int.
So there are three of the char* sort. I think now I won't forget about that
anymore. You definitely never stop learning. o_o

-Andreas

Nov 8 '08 #9

P: n/a

"Eric Sosman" <Er*********@sun.comwrote:
Are you sure the error message matches the code you have shown?
If so, report the bug[*] to your compiler vendor. (Or upgrade to a
newer version. For what it's worth, your code elicits a warning from
gcc 4.3.2,
Bingo. I was getting this with 4.3.2 indeed.
but with that version the warning is correct.)
Yup. Note that my post definitely was _not_ a complaint of that "gcc guys,
please fix your software" sort, but simply a presumption that I might have
forgotten about something. :) However, I could not sense that there are
three distinct char * types, unlike the int types which are either unsigned
or signed---thus two---and that's about it.

-Andreas

Nov 8 '08 #10

P: n/a

"Stephen Sprunk" <st*****@sprunk.orgschrieb:
When working with strings, always use (char *).
Promised henceforth. :)
Since I know there are 3 distinct subtypes, which blatantly escaped me. Doh.

-Andreas

Nov 8 '08 #11

P: n/a
CBFalconer <cb********@yahoo.comwrites:
Andreas Eibach wrote:
>>
... snip ...
>>
So I will stick to using _signed_ char* in the strcmp(), even
though I'm not needing negative values. Looks like strcmp()
does not accept unsigned char*, even though both arguments are
now of same type.

No. You should recognize that there are three distinct types of
chars in C. char, signed char, and unsigned char. They are
distinct.
Right.
For any implemented C system char has been set to be one
of signed char, or unsigned char. You don't necessarily know
which.
And here you contradict your earlier statement. I know what you
meant, but it's not quite what you said. For any C implementation,
type char isn't "set to be" either signed char or unsigned char; it's
set to have the same characteristics (size, range, representation) as
either signed char or unsigned char. It's still a distinct type, as
you correctly stated above.

For example:

char *pc = NULL;
unsigned char *puc;
signed char *psc;
puc = pc; /* constraint violation */
psc = pc; /* constraint violation */

*Both* marked lines are constraint violations, regardless of the
signedness of plain char.
What you do know is that strings are represented by arrays
of char (with a '\0' terminator), and are passed as pointers to
char (char*).
String literals certainly are. I think that the standard's definition
of "string", as "a contiguous sequence of characters terminated by and
including the first null character", allows an array of unsigned char
to contain a "string"; a "character" can be either a char, a signed
char, or an unsigned char.
It looks as if your system has char set to be signed char. Don't
assume this in general.
You mean "set to have the same representation as".

--
Keith Thompson (The_Other_Keith) ks***@mib.org <http://www.ghoti.net/~kst>
Nokia
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"
Nov 8 '08 #12

P: n/a
Andreas Eibach wrote:
"Eric Sosman" <Er*********@sun.comwrote:
> Are you sure the error message matches the code you have shown?
If so, report the bug[*] to your compiler vendor. (Or upgrade to a
newer version. For what it's worth, your code elicits a warning from
gcc 4.3.2,

Bingo. I was getting this with 4.3.2 indeed.
Apparently I was being too subtle. Let me try again:
"Andreas, you are lying. The code you showed did *not*
elicit the warning you showed, and you are guilty of
mis-reporting. The `this' you mention was in fact
`something else'."

I'm pretty sure I know what mistake you made, and I
know what message you actually got (or, if you actually
got that message, what your code actually looked like).
The point of the scolding is simply this: When you report
that "Code X gave me message Y," do not replace X and Y
by W and Q! It's bad for the diagnosis.

"Doctor, I have this terrible pain in my left ankle."
"I see nothing wrong with your left ankle." "Oh, what I
really meant was my right hip ... maybe. Guess again."

--
Eric Sosman
es*****@ieee-dot-org.invalid
Nov 8 '08 #13

P: n/a

"Eric Sosman" <es*****@ieee-dot-org.invalidschrieb:
Apparently I was being too subtle. Let me try again:
"Andreas, you are lying. The code you showed did *not*
elicit the warning you showed, and you are guilty of
mis-reporting. The `this' you mention was in fact
`something else'."
Yes, Your Honor. :P

-Andreas
Nov 8 '08 #14

This discussion thread is closed

Replies have been disabled for this discussion.