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.
You can change the signature of function
PyTuple_GetByte
to expect achar*
parameter.You need to convert your input variable from type
char*
to typeunsigned char*
, before you can pass it intoPyTuple_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:
- Should I use
static_cast
orreinterpret_cast
to work with a pointer to the underlying bit pattern of an object without concern for the object type? - If I should use
reinterpret_cast
is avoid*
or achar*
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 themem
functions provided in thecstring
libraryread
andwrite
usechar*
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
Getting the Current Time (In Milliseconds) from the System Clock in Windows
Stl Map Should Use Find() or [N] Identifier to Find Element in Map
What Can a 'Const' Method Change
Brute-Force, Single-Threaded Prime Factorization
What Is the Use of Volatile Keyword
Qthread Emits Finished() Signal But Isrunning() Returns True and Isfinished() Returns False
Can #If Pre-Processor Directives Be Nested in C++
Getting a Buffer into a Stringstream in Hex Representation:
In C++ I Cannot Grasp Pointers and Classes
Interfaces VS Templates for Dependency Injection in C++
Member Initializer Does Not Name a Non-Static Data Member or Base Class
Getting a Bunch of Crosses Initialization Error
Clean Up Your #Include Statements
Does Std::Array<> Guarantee Allocation on the Stack Only
G++: in What Order Should Static and Dynamic Libraries Be Linked
Is It Ever Not Safe to Throw an Exception in a Constructor