C++ type casting with pointers

20,860

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;
...
Share:
20,860
UnTraDe
Author by

UnTraDe

Updated on February 23, 2020

Comments

  • UnTraDe
    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
      tenfour almost 12 years
      In 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
      Rndm almost 12 years
      Do you want to know about casting with pointers in general or from your example it may seem the difference between casting to char * and char const * ?
    • UnTraDe
      UnTraDe almost 12 years
      I edited the post, now it should be more clear I think.
    • jahhaj
      jahhaj almost 12 years
      Neither of your examples compile, so they are not meaningful.
    • CapelliC
      CapelliC almost 12 years
      after the edit the code can't compile: should be char c = *((char*)x);
    • UnTraDe
      UnTraDe almost 12 years
      I 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
      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
      UnTraDe almost 12 years
      I edited it and I think now it should compile and explain what is the question more clearly.
    • Lexi
      Lexi almost 12 years
      Where did you come across code that casts with *s anyway?
    • jahhaj
      jahhaj almost 12 years
      What 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.