Casting in C++
C++ has a couple different conventions for casting a standard data type and user created objects from one object type to another. This page will try to help determine which cast to use in different situations and what problems might arise when casting.
Casting in C++ is when one data type is converted into another data type.
The two ways to cast in C++ is either Implicit Casting or Explicit Casting.
Implicit Casting:
The compiler determines when to cast without the programmer adding any special code to do so.
Casting in C++ is when one data type is converted into another data type.
The two ways to cast in C++ is either Implicit Casting or Explicit Casting.
Implicit Casting:
The compiler determines when to cast without the programmer adding any special code to do so.
This is a fairly straightforward concept but still one that can cause questions when switching from another programming language. C++ has a couple different conventions for copying variables. The simplest way is to assign the variable you want to copy to the new variable of the same type.
Explicit Casting:
For explicit casting, the programmer must explicitly tell the compiler they want to perform a cast.
There are four types of casting operators in C++:
- static_cast
- const_cast
- reinterpret_cast
- dynamic_cast
Static Cast:
This is a compile time cast. Similar to implicit casting with a few more compiler checks to make sure the data you are trying to convert can actually be converted.
This is a compile time cast. Similar to implicit casting with a few more compiler checks to make sure the data you are trying to convert can actually be converted.
Const Cast:
Used to remove the const-ness from references and pointers that ultimately point to something that is not const.
This is not meant to remove the const from a const variable. Using const_cast to assigned a value to a constant variable results in undefined behavior.
reinterpret_cast:
The "with great power comes great responsibility" cast. The reinterpret_cast can convert one pointer to another pointer of any type.
This can be used when passing data from one data type to another data type. But be careful!
This will not check if the data and the pointer type are the same, so use with caution. Data can easily get lost when using this.
In the example below, a uint32_t variable called secret is given a hex value. A uint32_t is an unsigned integer that is 32bit longs (4 bytes). The secret value is then assigned to a char pointer using reinterpret_cast, even though a char pointer can only point to 8 bits of data!
Never fear, this is okay to do if done correctly. The variable secret is 32 bits long or 4 bytes, each byte is exactly 2 hex numbers long. If we divide up the large number seen assigned to secret it would be (65) (64) (6F) (63).
Since the variable secretLetter is a char pointer, it will point to the first 8 bits of data held within the 32 bit secret variable. This turns out to be the hex value 0x63 which looking at an ascii table, is the character 'c'!
The 'c' gets printed out and then the pointer gets incremented. This will now change to pointer to see the next 8 bits inside the secret variable, 0x6F which is the ascii character 'o'.
The code increments the pointer two more times and will print out the two final characters, 'd' and 'e' to make the secret word "code"!
But wait...why did the pointer first point to 0x63 instead of 0x65? The secret variable has the 0x65 as the first number!
This is because the system used to write this was a little-endian machine.
There are two main types of ways computers store bytes, little-endian and big-endian. In little-endian, the "smallest" byte gets stored first. When we write numbers on paper, like the number 11,245, the smallest part of that number is '5'. This is the same for a little-endian machine. The number 0x65646F63 will have the right-most side as the smallest part of the number, which is 0x63!
This is why the pointer will see the 0x63 as the first byte that the char pointer will read, printing the word "code" instead of "edoc" (which is "code" backwards)
This is another reason reinterpret_cast is so challenging, you have to know a good amount of how computers store data and how large your variable is. If not, you could be pointing to the wrong location in memory, causing errors that would be hard to track down!
Use with caution, and have fun!
Since the variable secretLetter is a char pointer, it will point to the first 8 bits of data held within the 32 bit secret variable. This turns out to be the hex value 0x63 which looking at an ascii table, is the character 'c'!
The 'c' gets printed out and then the pointer gets incremented. This will now change to pointer to see the next 8 bits inside the secret variable, 0x6F which is the ascii character 'o'.
The code increments the pointer two more times and will print out the two final characters, 'd' and 'e' to make the secret word "code"!
But wait...why did the pointer first point to 0x63 instead of 0x65? The secret variable has the 0x65 as the first number!
This is because the system used to write this was a little-endian machine.
There are two main types of ways computers store bytes, little-endian and big-endian. In little-endian, the "smallest" byte gets stored first. When we write numbers on paper, like the number 11,245, the smallest part of that number is '5'. This is the same for a little-endian machine. The number 0x65646F63 will have the right-most side as the smallest part of the number, which is 0x63!
This is why the pointer will see the 0x63 as the first byte that the char pointer will read, printing the word "code" instead of "edoc" (which is "code" backwards)
This is another reason reinterpret_cast is so challenging, you have to know a good amount of how computers store data and how large your variable is. If not, you could be pointing to the wrong location in memory, causing errors that would be hard to track down!
Use with caution, and have fun!