Why Can't I Static_Cast Between Char * and Unsigned Char *

Why can't I static_cast between char * and unsigned char *?

They are completely different types see standard:

3.9.1 Fundamental types [basic.fundamental]

1 Objects declared as characters char) shall be large enough to
store any member of the implementation's basic character set. If a
character from this set is stored in a character object, the integral
value of that character object is equal to the value of the single
character literal form of that character. It is
implementation-defined whether a char object can hold negative
values. Characters can be explicitly declared unsigned or

signed. Plain char, signed char, and unsigned char are
three distinct types.
A char, a signed char, and an unsigned char
occupy the same amount of storage and have the same alignment
requirements (basic.types); that is, they have the same object
representation. For character types, all bits of the object

representation participate in the value representation. For unsigned
character types, all possible bit patterns of the value representation
represent numbers. These requirements do not hold for other types. In
any particular implementation, a plain char object can take on either
the same values as a signed char or an unsigned char; which one is
implementation-defined.

So analogous to this is also why the following fails:

unsigned int* a = new unsigned int(10);
int* b = static_cast<int*>(a); // error different types

a and b are completely different types, really what you are questioning is why is static_cast so restrictive when it can perform the following without problem

unsigned int a = new unsigned int(10);
int b = static_cast<int>(a); // OK but may result in loss of precision

and why can it not deduce that the target types are the same bit-field width and can be represented? It can do this for scalar types but for pointers, unless the target is derived from the source and you wish to perform a downcast then casting between pointers is not going to work.

Bjarne Stroustrop states why static_cast's are useful in this link: http://www.stroustrup.com/bs_faq2.html#static-cast but in abbreviated form it is for the user to state clearly what their intentions are and to give the compiler the opportunity to check that what you are intending can be achieved, since static_cast does not support casting between different pointer types then the compiler can catch this error to alert the user and if they really want to do this conversion they then should use reinterpret_cast.

C++ how to convert from char * to unsigned char * in function call?

From the error, the signature of the PyTuple_GetByte function was expecting a third parameter of type unsigned char*, but you passed a variable of type char* at its invocation. I think you have two options here.

  1. You can change the signature of function PyTuple_GetByte to expect a char* parameter.

  2. You need to convert your input variable from type char* to type unsigned char*, before you can pass it into PyTuple_GetByte.

The conversion is normally like this:

unsigned char* convert_var = reinterpret_cast<unsigned char*>(&SourceCell.window_type); // (c++ way)

or

unsigned char* convert_var = (unsigned char*)(&SourceCell.window_type); // (c way)

If I want to promote a char to an int, should I use static_cast<int>(char variable) or +(char variable) and why?

IMO, there is one important advantage of using static_cast, even if it is a little bit more verbose: it allows you to quickly search your code for casts via grep or any other text searching utility. In large projects this may make the difference, since otherwise C-style casts are often mistakenly matched in functions declarations such as void f(double), where (double) is of course not a cast.

Moreover, static_cast makes perfectly clear your intention. Using the + operator may seem exotic (incomprehensible) to someone who is not 100% familiar with integer promotions rules. In terms of "safety", afaik, both are equally good.

Related: What is the difference between static_cast<> and C style casting?

Why can't an unsigned char properly display a hex value

cout is specialized to output the char type as a character, not a number. That goes for unsigned chars too. You get around it by casting to an unsigned int.

cout << hex << setw(2) << setfill('0') << static_cast<unsigned int>(state[x][y]) << " ";

Why can I use static_cast With void* but not With char*

Your question really has 2 parts:

  1. Should I use static_cast or reinterpret_cast to work with a pointer to the underlying bit pattern of an object without concern for the object type?
  2. If I should use reinterpret_cast is a void* or a char* preferable to address this underlying bit pattern?

static_cast: Converts between types using a combination of implicit and user-defined conversions

In 5.2.9[expr.static.cast]13 the standard, in fact, gives the example:

T* p1 = new T;
const T* p2 = static_cast<const T*>(static_cast<void*>(p1));

It leverages the implicit cast:

A prvalue pointer to any (optionally cv-qualified) object type T can be converted to a prvalue pointer to (identically cv-qualified) void. The resulting pointer represents the same location in memory as the original pointer value. If the original pointer is a null pointer value, the result is a null pointer value of the destination type.*

There is however no implicit cast from a pointer of type T to a char*. So the only way to accomplish that cast is with a reinterpret_cast.

reinterpret_cast: Converts between types by reinterpreting the underlying bit pattern

So in answer to part 1 of your question when you cast to a void* or a char* you are looking to work with the underlying bit pattern, reinterpret_cast should be used because it's use denotes to the reader a conversion to/from the underlying bit pattern.

Next let's compare void* to char*. The decision between these two may be a bit more application dependent. If you are going to use a standard library function with your underlying bit pattern just use the type that function accepts:

  • void* is used in the mem functions provided in the cstring library
  • read and write use char* as inputs

It's notable that C++ specific libraries prefer char* for pointing to memory.
Holding onto memory as a void* seems to have been preserved for compatibility reasons as pointer out here. So if a cstring library function won't be used on your underlying bit patern, use the C++ specific libraries behavior to answer part 2 of your question: Prefer char* to void*.

ifstream::read not reading unsigned char, even with reinterpret_cast

[Updated] This should work:

int pix[3]; // not an unsigned char
...
ifs >> pix[0] >> pix[1] >> pix[2];

instead of:

ifs.read(reinterpret_cast<char *>(pix), 3);

Like you do for width and height?

ifs >> w >> h >> max;

C++: can't static_cast from double* to int*

Aside from being pointers, double* and int* have nothing in common. You could say the same thing for Foo* and Bar* pointer types to any dissimilar structures.

static_cast means that a pointer of the source type can be used as a pointer of the destination type, which requires a subtype relationship.

Convert unsigned char[10] to QBytearray;

It's just signedness issue, so this should work:

databuf = QByteArray(reinterpret_cast<char*>(buf), 10);

Or with legacy C-style cast:

databuf = QByteArray((char*)buf, 10);

(Here's one of many many discussions about which you should use.)

Easier alternative is to remove unsigned from declaration of buf, if you don't need it there for some other reason.

Note, that if you use that fromRawData method, it does not copy the bytes, so better be sure buf won't go out of scope too soon. If unsure, do not use it...

How to properly convert std::string to an integer vector

However C++ code outputs [116, 101, 115, 116, -50, -108].

In C++, the char type is separate from both signed char and unsigned char, and it is unspecified whether or not it should be signed.

You thus explicitly want an unsigned char*, but the .c_str method gives you char *, so you need to cast. You will need reinterpret_cast or a C-style cast; static_cast will not work.



Related Topics



Leave a reply



Submit