C++ type casting with pointers
Solution 1
In both your examples you're making mistakes making the code not compile. So I'll assume you're trying to do the following:
int x = 1;
char c = *((char*)&x);
Depending on your architecture, c
will now have either the value of the least or the most significant byte of x
. In this example this would be either 0 or 1 (this can actually be used to detect the byte ordering).
Your second example won't work, cause you're trying to ignore the const
resulting in an illegal operation/bad cast (this is also called "const correctness").
Edit: Regarding your comment about "what does it mean?":
In expressions:
&somevariable
will return the address of somevariable
.
*somevariable
will assume the contents of somevariable
are the address of the actual value, which is then returned.
In declarations:
datatype
is a normal variable/object. This is passed "by value".
datatype&
is a reference. This works exactly like normal variables in Java/C# and is passed by reference.
datatype*
is a pointer. This just contains the address where the actual value is located (see above) and is essentially passed by reference as well.
Actual casts work pretty much similar to Java/C#, but pointers are just that: They point to the location of the actual value. While this might confuse you, pointers in C/C++ work pretty much like the standard variables/references used in Java/C#.
Look at this:
MyClass x; // object of MyClass
MyClass *x; // pointer to an object of MyClass - the actual value is undefined and trying to access it will most likely result in an access violation (due to reading somewhere random).
MyClass *x = 0; // same as above, but now the default value is defined and you're able to detect whether it's been set (accessing it would essentially be a "null reference exception"; but it's actually a null pointer).
MyClass &x = MyClass(); // creating a new reference pointing to an existing object. This would be Java's "MyClass x = new MyClass();"
Solution 2
Casting in C++ works just like casting in Java, no pointers involved.
int x = 1;
char c = (char) x; // Lose precision
However, what you are doing here:
int x = 1;
char *c = (char *)x;
is telling the compiler that the value of x
is the address of a character. It is equivalent to
char *c;
c = 1; // Set the address of c to 0x0000000000000001
There are very few times you need to do this.
Solution 3
There are two fundamentally different concepts in C++ which are both sometimes referred to as "casting": One is conversion, and one is reinterpretation.
Conversion creates a new object with the "same value" as an existing object, but of a different type. Here are some examples:
Example 1: type promotion
// 1a: promote int to double to get the correct type of division
int numerator = rand(), denominator = rand();
double d = double(numerator) / double(denominator);
// 1b: convert int to double to achieve a particular argument deduction
int n;
template <typename T> void do_numeric_stuff(T x) { /* ... */ }
do_numeric_stuff(double(n));
Example 2: Derived-to-base conversion
struct B { }; struct D : B { };
D x;
D * p = &x; // pointer to x
B * q = p; // implicit conversion; may change the value!
On the other hand, reinterpretation allows us to treat one variable as though it was another one. About the only correct and useful application for this is serialization, in one form or another.
Example 3: Serialization
std::ofstream file("output.bin"); // output file
char large_buffer[HUGE]; // in-memory buffer
unsigned int n = get_data();
char const * p = reinterpret_cast<char const *>(&n);
file.write(p, p + sizeof n); // write the bytes of `n`
std::copy(p, p + sizeof n, large_buffer); // ditto
std::copy(large_buffer + 17, large_buffer + 17 + sizeof n,
reinterpret_cast<char *>(&n)); // repopulate `n` from buffer
The standard says that it is undefined behaviour to access an object through a pointer that is not of the correct type (also called "type punning"). While it is OK to store an object pointer in, say, a void*
and then convert it back and use it, it is not OK to treat a float as though it was an integer, etc. The only acceptable way of accessing one object as though it was another is the one I demonstrated, namely treating an object of type T
as though it was an array char[sizeof(T)]
— that is, you are allowed to access the underlying binary representation of every object.
Solution 4
You should avoid c-type casts like (char*) by all means. If you really have to do a type cast have a look at dynamic_cast
, static_cast
and reinterpret_cast
.
But as already stated, you rarely need casting at all.
Have a look here for fruther information: http://www.cplusplus.com/doc/tutorial/typecasting/
http://www.parashift.com/c++-faq/static-typing-and-cpp.html
http://www.parashift.com/c++-faq-lite/print-char-or-ptr-as-number.html
Solution 5
I used many time ago that idiom to access HW at specified address, on custom IO board. So for instance to write at PIC (programmable interrupt controller) to reset some flag (fictious code):
#define PIC_LOC 0x1000
#define PIC_ENABLE_PORT *((char*)(PIC_LOC+0x10))
#define BIT_ENABLE (1 << 3)
...
PIC_ENABLE_PORT |= BIT_ENABLE;
...
UnTraDe
Updated on February 23, 2020Comments
-
UnTraDe about 4 years
I come from a background of C# and Java and I can't seem to understand what casting with pointers means in C++.
For example:
int x = 1; char c = *((char*)&x);
What does it do? What it is useful for?
-
tenfour almost 12 yearsIn C++ you should avoid casting. Casting is a way to tell the compiler "no, no, you will think this is wrong but I'm sure I'm right". In C++ though it's always better to make the compiler right all the time. Casting is a way of suppressing compiler errors. So basically it's more constructive to ask about casting for a particular purpose, rather than casting in general. Both of your examples should be avoided in C++ entirely.
-
Rndm almost 12 yearsDo you want to know about casting with pointers in general or from your example it may seem the difference between casting to
char *
andchar const *
? -
UnTraDe almost 12 yearsI edited the post, now it should be more clear I think.
-
jahhaj almost 12 yearsNeither of your examples compile, so they are not meaningful.
-
CapelliC almost 12 yearsafter the edit the code can't compile: should be
char c = *((char*)x);
-
UnTraDe almost 12 yearsI want to know what is no in the variable c for example what it is mean to cast with the symbol *. I'm coming from a background of c# and java so and I don't know if it is only me but I use casting in those languages for converting from double to float and that kind of stuffs.
-
jahhaj almost 12 years@UnTraDe, you at least need to post an example that compiles, but even if you do that it doesn't mean that it is legal C++. Sometimes in C++ you have a pointer to one type, but really you know it's a pointer to another type, so you cast it.
-
UnTraDe almost 12 yearsI edited it and I think now it should compile and explain what is the question more clearly.
-
Lexi almost 12 yearsWhere did you come across code that casts with *s anyway?
-
jahhaj almost 12 yearsWhat your examples do it take the integer value 1, and pretend it's a pointer. Of course it's very unlikely that 1 represents a legal memory address, so any program that used this 'pointer' is very likely to crash quite quickly.
-