2

So I have an

unsigned char * pMyPtr 

assigned to something.

Then I want to compare this to an arbitrary string with

strcmp(const char* , const char* )

But when I do that, clang compiler tells me

warning: passing (aka 'unsigned char *') to parameter of type 'const char *' converts between pointers to integer types with different sign

How do I remove this warning?

Filip Roséen - refp
  • 62,493
  • 20
  • 150
  • 196
user1343318
  • 2,093
  • 6
  • 32
  • 59

4 Answers4

6

With all the comments to the question, I feel like I'm missing something.

I know that casts are unfashionable, but isn't the following a simple workaround?

strcmp((const char*) pMyPtr , whatever_is_being_compared)
Michael Burr
  • 333,147
  • 50
  • 533
  • 760
  • Yes. And if you don't like swamping the client code with casts, hide it in a wrapper function that takes `unsigned char *` as argument. – M Oehm Jun 04 '14 at 06:21
  • But note that signed integer overflow is still undefined behaviour in C++. – juanchopanza Jun 04 '14 at 06:38
  • 2
    @juanchopanza: where would signed integer overflow come into play here? – Michael Burr Jun 04 '14 at 06:58
  • Wouldn't interpreting an `unsigned char` of value greater than `numeric_limits::max()` as a `char` (for a signed `char` implementation) constitute overflow? Or maybe I am just too confused this morning, in which case I apologize. – juanchopanza Jun 04 '14 at 07:00
  • 2
    @juanchopanza: It's not casting the `unsigned char` to a `char`; it's casting the pointer to an `unsigned char` to a pointer to a `char`. In effect, that will reinterpret the bits in the pointed at byte array. I think that a `signed char` whose bits are all set is allowed to be a trap representation (at least on a one's complement machine), so the reinterpret_cast is technically unsafe, but in practice one's-complement machines with trapping 0377 characters are probably even rarer than machines which trap on integer overflow. – rici Jun 04 '14 at 07:25
  • Even though `strcmp()` takes plain `char*` arguments, it defined to act on the characters as `unsigned char` anyway: "The sign of a nonzero value returned by the comparison functions `memcmp`, `strcmp`, and `strncmp` is determined by the sign of the difference between the values of the first pair of characters **(both interpreted as unsigned char)** that differ in the objects being compared." – Michael Burr Jun 04 '14 at 07:37
  • 1
    @MichaelBurr: Wearing the language lawyer hat, I don't think the fact that `strcmp` casts each (possibly signed) `char` to an `unsigned char` avoids the (highly theoretical) problem that the original `unsigned char` might be a trap representation if read as a `char`. That is, the language in the definition of `strcmp` still allows it to use either `*(unsigned char*)arg` or `(unsigned char)*arg` to do the reinterpretation, both of which are well-defined, afaik. But it's all dancing angels, no? – rici Jun 04 '14 at 07:43
  • @rici I know it is casting a pointer. Which means you re-interpret the bits of an `unsigned char` as those of a (possible signed) `char` when you de-reference the data pointed at by the casted pointer. But if `strcmp` is designed to cope with this, my point is moot. – juanchopanza Jun 04 '14 at 07:53
  • @rici: my understanding is that lvalue expressions with character type, whether signed or not, cannot trap (according to 6.2.6.1/5 in the C standard). – Michael Burr Jun 04 '14 at 08:05
  • @MichaelBurr I wrote [this](http://stackoverflow.com/q/24032322/1090079) *Q&A* to answer your question(s). – Filip Roséen - refp Jun 04 '14 at 08:22
  • @rici I wrote [this](http://stackoverflow.com/q/24032322/1090079) *Q&A* to answer your question(s). – Filip Roséen - refp Jun 04 '14 at 08:22
  • @juanchopanza I wrote [this](http://stackoverflow.com/q/24032322/1090079) *Q&A* to answer your question(s). – Filip Roséen - refp Jun 04 '14 at 08:22
  • @juanchopanza The data is obviously strings. Have you ever heard of a symbol table using negative indices? Why would the unsigned char contain anything in that would get interpreted as a sign bit? If it did, there's a bug elsewhere in the code and not related to the strcmp call. In other words, if the unsigned char contained anything that would possibly be interpreted as a trap representation when converted to char, it seems unlikely that the value of the unsigned char could be used to represent a valid symbol, which is the whole purpose of it in this case. – Lundin Jun 04 '14 at 10:34
  • @Lundin `unsigned char` can hold values that a `char` cannot. Overflowing a signed integer is undefined behaviour. I don't care much about the rest, I can't speculate about the contents of a block of `unsigned char` data. – juanchopanza Jun 04 '14 at 10:36
  • @juanchopanza If you use unsigned char for strings, as must be the case if you are using strcmp, then it doesn't make sense to have the unsigned char holding anything that char cannot, _because the size and signedness of the char type is selected based on the local symbol table_. The char type is therefore large enough to print all the symbols you could possibly want. So if you store something larger than CHAR_MAX in your unsigned char, you have an application bug. – Lundin Jun 04 '14 at 10:43
  • (And wearing the language lawyer hat, overflowing a signed integer does not necessarily lead to UB: the implementation could support negative zeroes. See C11 6.2.6/3.) – Lundin Jun 04 '14 at 10:44
5

It isn't even unsigned. Behind it, is a struct.

This means that you cannot use strcmp here. You can use strcmp when the input data are null-terminated strings. That's not the case when the input data are structs. Perhaps you should consider memcmp instead, or perhaps you need to compare the structs as structs.

David Heffernan
  • 601,492
  • 42
  • 1,072
  • 1,490
1

Clang can't convert from unsigned char* to const char*. That because unsigned char* is different then char*. By adding unsiged you make the range of char 0to255 instead of -127to127.

On the line where strcmp goes, you can typecast the unsigned char value with (const char*) which will work, because there it will be threated as a const char*. instead of unsigned char

Edenia
  • 2,312
  • 1
  • 16
  • 33
  • 1
    `char` has implementation-defined signedness. It may be unsigned and range from 0-255 or it may be signed and range from -128 to 127 (assuming two's complement). – Lundin Jun 04 '14 at 06:30
  • For C++, it treats `char`, `signed char` and `unsigned char` as three distinct different types. – hlovdal Jun 04 '14 at 06:38
  • @hlovdal Yes, i know. But i also mention about C. – Edenia Jun 04 '14 at 06:52
1

If you feel that warning does not have any side effect. you can ignore the warning like this:

#pragma warning( disable : 4507 34 )
Anil8753
  • 2,663
  • 4
  • 29
  • 40
  • Disable warning messages 4507 and 4034. – Anil8753 Jun 04 '14 at 06:56
  • Bad advice. Don't disable warnings if you don't know what this is about. Here obviously just the wrong tool is used. Using a string comparison function for binary data is just the wrong idea. When using the correct function (`memcmp`) there will be no warning since it has the correct signature. – Jens Gustedt Jun 04 '14 at 07:41
  • 1
    @JensGustedt, I said, "If you feel that warning does not have any side effect", Yeah, memcmp is good way to go. :) – Anil8753 Jun 04 '14 at 08:18