Reputation: 712
I want to cast a pointer pc
which points to char to a point pi
which points to int
char *pc;
int *pi;
pi = (int*)pc // compiler complaint about old-style cast
pi = static_cast<int *>(static_cast<void *>(pc)) // no complaint any more but too complex
is there any simpler ways to do this cast and make compiler silence?
Upvotes: 3
Views: 6521
Reputation: 170044
I want to put the back and forth under @Bathsheba's post to rest. So here's an answer about the finer details of what you are doing.
@Sean already suggested you reinterpret_cast
your pointers instead. And that is equivalent to your second chain of casts. It says as much in [expr.reinterpret.cast]/7:
An object pointer can be explicitly converted to an object pointer of a different type. When a prvalue
v
of object pointer type is converted to the object pointer type “pointer to cvT
”, the result isstatic_cast<cv T*>(static_cast<cv void*>(v))
. [ Note: Converting a prvalue of type “pointer toT1
” to the type “pointer toT2
” (whereT1
andT2
are object types and where the alignment requirements ofT2
are no stricter than those ofT1
) and back to its original type yields the original pointer value. — end note ]
Now, let's examine each step of the two step conversion. First we have a static_cast<void*>
. According to [conv.ptr]/2 (emphasis mine):
A prvalue of type “pointer to cv
T
”, whereT
is an object type, can be converted to a prvalue of type “pointer to cvvoid
”. The pointer value is unchanged by this conversion.
The first conversion doesn't do any alteration to the address. And then it also says in [basic.compound]/5:
A pointer to cv-qualified or cv-unqualified
void
can be used to point to objects of unknown type. Such a pointer shall be able to hold any object pointer. An object of type cvvoid*
shall have the same representation and alignment requirements as cvchar*
.
So a char*
may store any address a void*
may store. Now it doesn't mean the conversion from void*
to char*
is value preserving, only that they can represent the same values. Now, assuming a very restricted use case, that is enough of a guarantee. But there's more at [expr.static.cast]/13:
A prvalue of type “pointer to cv1 void” can be converted to a prvalue of type “pointer to cv2 T”, where T is an object type and cv2 is the same cv-qualification as, or greater cv-qualification than, cv1. If the original pointer value represents the address A of a byte in memory and A does not satisfy the alignment requirement of T, then the resulting pointer value is unspecified. Otherwise, if the original pointer value points to an object a, and there is an object b of type T (ignoring cv-qualification) that is pointer-interconvertible with a, the result is a pointer to b. Otherwise, the pointer value is unchanged by the conversion.
Where am I going with this? Assuming pc
already holds the address of an int
(suitably converted according to the above), then casting the char*
to an int*
via reinterpret_cast
will give you the address of the original int
. The note under the first paragraph says as much, and the further quotes prove it. If it doesn't hold the address of an int
, you are playing roulette and are likely going to lose. Your program has undefined behavior. You should follow Bathsheba's advice to the letter.
Upvotes: 3
Reputation: 234635
The behaviour on converting, in general, a char*
pointer to an int*
pointer is undefined. Dereferencing such a pointer will cause you further trouble as you will be breaking strict aliasing rules. Note that the C++ Standard does not require sizeof(char*)
to be the same as sizeof(int*)
.
(Note that converting an unsigned char*
pointer to an int*
is well-defined if the unsigned char*
pointer actually points to an int
).
Don't do it. Ever.
Upvotes: 7
Reputation: 62472
If you really need to do this then reinterpret_cast is your friend:
char *pc = 0;
int *pi = 0;
pi = reinterpret_cast<int*>(pc);
Upvotes: 7