Incompatibility between char* and unsigned char*?
Asked Answered
S

3

5

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?
Shontashoo answered 8/3, 2018 at 5:14 Comment(4)
noting really to makes you worry, just strcpy( (char*)var, "string");Barfuss
char, signed char and unsigned char are distinct types. You can't use an unsigned char * where a char * is expected, and vice versa, without using type casts. But why are you passing an unsigned char * to a char * based API to begin with? What kind of data does the unsigned char * point to? You might consider using memcpy() instead.Poltroon
It would be helpful to include an MCVE in this question showing the definition of var. It would also be helpful to include the version of HP-UX and/or the compiler you're using.Bertberta
The second question is a duplicate of How to convert a string literal to unsigned char array in visual c++Pb
C
4

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.

Circumfuse answered 8/3, 2018 at 5:25 Comment(3)
But if they can alias each other then what is the rationale in making the compiler throw an error? Is there some edge case that would make the cast unsafe?Shontashoo
@M.Hassaan I think it's just general type safety helping you avoid accidentally using the wrong variable. By making the user provide an explicit cast it helps to ensure you know what they are doing. The cast is always safe respecting strict aliasing rules.Circumfuse
It should be reinterpret_castIsochronism
M
1

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 *'

Milner answered 8/3, 2018 at 7:9 Comment(0)
V
1

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).

Vineyard answered 8/3, 2018 at 7:54 Comment(1)
By "forcing the compiler" do you mean casting? And could you kindly give an example in your answer of a scenario in which using strcpy() in this way would cause unwanted behavior?Shontashoo

© 2022 - 2024 — McMap. All rights reserved.