1

Below is the simple code:

unsigned char buf[255];
unsigned char msg[255];

while((res = read (fd, buf, (sizeof buf)-1)) > 0)
{
   buf[res] = '\0';
   strcat(msg, buf);
   length += res;
   if(length >= 10)
        break;
}

This line strcat(msg, buf); gives below warning:

warning: pointer targets in passing argument 1 of ‘strcat’ differ in signedness

I have tried every solution found for the similar question but didnt helped much. Can anyone please help why this is giving error when both variable are of same signedness. How can I remove it. Thanks

Edit:

unsigned const char *buf[255];
unsigned char *msg[255];
strcat(msg, buf);

Now it gives warning:

warning: passing argument 2 of ‘strcat’ from incompatible pointer type
Sourav Ghosh
  • 133,132
  • 16
  • 183
  • 261
Doe
  • 45
  • 1
  • 8
  • 3
    @Doe DeiDei didn't tell you to change anything, and your changes make no sense (and have nothing to do with what DeiDei said). – melpomene May 16 '17 at 05:21
  • The 'signedness' problem refers to 'unsigned', not 'const' – Déjà vu May 16 '17 at 05:23
  • @ringø Yes both the char are unsigned then why its showing warning. When I remove unsigned, it shows no warning – Doe May 16 '17 at 05:28
  • 1
    Because 'strcat' arguments are declared *without* 'unsigned' (i.e. it deals with signed chars) – Déjà vu May 16 '17 at 05:29
  • 1
    The function expects plain `char *`; you're passing `unsigned char *`. These are different types (even when plain `char` is an unsigned type). The `str*()` functions are not designed to take arrays of `unsigned char`. To 'placate' (or 'coerce') the compiler into accepting the call, you'll need to cast the pointers: `strcat((char *)msg, (char *)buf);`. Or write yourself a series of functions that do this automatically `static inline unsigned char *ustrcat(unsigned char *dst, const unsigned char *src) { return (unsigned char *)strcat((char *)dst, (char *)src); }` — good if do this a lot. – Jonathan Leffler May 16 '17 at 05:30
  • Casting is a way to solve this issue. – Déjà vu May 16 '17 at 05:35
  • @ringø actually it deals with plain chars (which may be signed or unsigned, but in either case, they are their own type) – M.M May 16 '17 at 05:36
  • BTW you should probably modify this loop to avoid overflowing `msg` – M.M May 16 '17 at 05:37
  • 1
    @ringø `strcat` arguments has no `unsigned` doesn't mean that it's `signed char`, because [`char` can be `signed` or `unsigned`](http://stackoverflow.com/q/2054939/995714) – phuclv May 16 '17 at 08:30

1 Answers1

0

Expanding my comment into something resembling an answer.

The strcat() function expects plain char *:

char *strcpy(char * restrict s1, const char * restrict s2);

You're passing unsigned char *. These are different types (even when plain char is an unsigned type). The str*() functions are not designed to take arrays of unsigned char. To 'placate' (or 'coerce') the compiler into accepting the call, you'll need to cast the pointers:

strcat((char *)msg, (char *)buf);

Or write and use a series of functions that do this automatically:

static inline unsigned char *ustrcat(unsigned char *dst, const unsigned char *src)
{
    return (unsigned char *)strcat((char *)dst, (char *)src);
}

This could be a good idea if you need to use the functions frequently; it means you don't have to leave so many unsightly casts around your code. You can add the restrict qualifiers if you prefer.


Note that the three types char, unsigned char and signed char are distinct, even though plain char has the same range of values as one of the other two. ISO/IEC 9899:2011 §6.2.5 Types says:

¶15 The three types char, signed char, and unsigned char are collectively called the character types. The implementation shall define char to have the same range, representation, and behavior as either signed char or unsigned char.45)

45) CHAR_MIN, defined in <limits.h>, will have one of the values 0 or SCHAR_MIN, and this can be used to distinguish the two options. Irrespective of the choice made, char is a separate type from the other two and is not compatible with either.


Your code is vulnerable to buffer overflows because you aren't checking lengths anywhere. This is tangential to the compilation warnings you're getting, but you should make sure that you do not copy too much data into the destination buffer.


You also tried:

unsigned const char *buf[255];
unsigned char *msg[255];
strcat(msg, buf);

Now you're passing pointers to pointers to a function that only expects pointers to char — the compiler is right to complain.

Community
  • 1
  • 1
Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278