Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Incompatibility between char* and unsigned char*?

The following line of code produces a compiler warning with HP-UX's C++ compiler:

strcpy(var, "string")

Output:

error #2167: argument of type "unsigned char *" 
    is incompatible with parameter of type "char *"

Please note: var is the unsigned char * here - its data type is outside of my control.

Two questions:

  1. What does incompatibility mean in the context of these two types? What would happen if the compiler was forced to accept the conversion? An example would be appreciated.
  2. What would be a safe way to make the above line of code work, assuming I have to use strcpy?
like image 428
Hassaan Avatar asked Mar 08 '18 05:03

Hassaan


People also ask

What is the difference between char and unsigned char?

An unsigned type can only represent postive values (and zero) where as a signed type can represent both positive and negative values (and zero). In the case of a 8-bit char this means that an unsigned char variable can hold a value in the range 0 to 255 while a signed char has the range -128 to 127.

Can you cast unsigned char to char?

However, from i=128:255 the chars and the unsigned chars cannot be casted, or you would have different outputs, because unsigned char saves the values from [0:256] and char saves the values in the interval [-128:127]).

Why there is signed and unsigned char?

Signed char and unsigned char both are used to store single character. The variable stores the ASCII value of the characters. For an example if 'A' is stored, actually it will hold 65. For signed char we need not to write the signed keyword.

Should I use signed or unsigned char?

Unsigned char must be used for accessing memory as a block of bytes or for small unsigned integers. Signed char must be used for small signed integers and simple char must be used only for ASCII characters and strings.


3 Answers

C++ is being strict in checking the types where std::strcpy expects a char* and your variable var is an unsigned char*.

Fortunately, in this case, it is perfectly safe to cast the pointer to a char* like this:

std::strcpy(reinterpret_cast<char*>(var), "string");

That is because, according to the standard, char, unsigned char and signed char can each alias one another.

like image 147
Galik Avatar answered Sep 24 '22 14:09

Galik


In C Standard, the char is Impementation Defined. ANSI C provides three kinds of character types(All three take one byte): char, signed char, unsigned char. Not just like short, int, only two.

You can try:

char *str="abcd"; signed char *s_str = str;

The compiler will warn the second line of the code is error.It just like:

short num = 10; unsigned short *p_num = &num;

The compiler will warn too. Because they are different type defined in compiler.

So, if you write 'strcpy( (char*)var, "string")',the code just copy the characters from "string"'s space to 'var's space. Whether there is a bug here depends on what do you do with 'var'. Because 'var' is not a 'char *'

like image 24
Gleipnir Avatar answered Sep 23 '22 14:09

Gleipnir


char, signed char, and unsigned char are distinct types in C++. And pointers to them are incompatible - for example forcing a compiler to convert a unsigned char * to char * in order to pass it to strcpy() formally results in undefined behaviour - when the pointer is subsequently dereferenced - in several cases. Hence the warning.

Rather than using strcpy() (and therefore having to force conversions of pointers) you would be better off doing (C++11 and later)

const char thing[] = "string";
std::copy(std::begin(thing), std::end(thing), var);

which does not have undefined behaviour.

Even better, consider using standard containers, such as a std::vector<unsigned char> and a std::string, rather than working with raw arrays. All standard containers provide a means of accessing their data (e.g. for passing a suitable pointer to a function in a legacy API).

like image 44
Peter Avatar answered Sep 25 '22 14:09

Peter