What static_cast<> is actually doing
By 2 Feb 2006
,
Introduction
Most programmers learn C before C++, and get used to C style casting. When writing C++, sometimes we may be confused about when to usestatic_cast<>
and when to use reinterpret_cast<>
. In this article, I will illustrate what static_cast<>
actually does, and will show some cases that will lead to errors.Generic Types
In short,float f = 12.3; float* pf = &f; // static cast<> // OK, n = 12 int n = static_cast<int>(f); // Error, types pointed to are unrelated //int* pn = static_cast<int*>(pf); // OK void* pv = static_cast<void*>(pf); // OK, but *pn2 is rubbish int* pn2 = static_cast<int*>(pv); // reinterpret_cast<> // Error, the compiler know you should // call static_cast<> //int i = reinterpret_cast<int>(f); // OK, but *pn is actually rubbish, same as *pn2 int* pi = reinterpret_cast<int*>(pf);
static_cast<>
will try to convert, e.g., float-to-integer, while reinterpret_cast<>
simply changes the compiler's mind to reconsider that object as another type.Pointer Types
Pointer casting is a bit complicated, we will use the following classes for the rest of the the article:class CBaseX { public: int x; CBaseX() { x = 10; } void foo() { printf("CBaseX::foo() x=%d\n", x); } }; class CBaseY { public: int y; int* py; CBaseY() { y = 20; py = &y; } void bar() { printf("CBaseY::bar() y=%d, *py=%d\n", y, *py); } }; class CDerived : public CBaseX, public CBaseY { public: int z; };
Case 1: Casting between unrelated classes
// Convert between CBaseX* and CBaseY* CBaseX* pX = new CBaseX(); // Error, types pointed to are unrelated // CBaseY* pY1 = static_cast<CBaseY*>(pX); // Compile OK, but pY2 is not CBaseX CBaseY* pY2 = reinterpret_cast<CBaseY*>(pX); // System crash!! // pY2->bar();
---
As we learnt in the generic types example, static_cast<>
will fail if you try to cast an object to another unrelated class, while reinterpret_cast<>
will always succeed by "cheating" the compiler to believe that the object is really that unrelated class.Case 2: Casting to related classes
1. CDerived* pD = new CDerived(); 2. printf("CDerived* pD = %x\n", (int)pD); 3. 4. // static_cast<> CDerived* -> CBaseY* -> CDerived* // OK, implicit static_cast<> casting 5. CBaseY* pY1 = pD; 6. printf("CBaseY* pY1 = %x\n", (int)pY1); // OK, now pD1 = pD 7. CDerived* pD1 = static_cast<CDerived*>(pY1); 8. printf("CDerived* pD1 = %x\n", (int)pD1); 9. 10. // reinterpret_cast // OK, but pY2 is not CBaseY* 11. CBaseY* pY2 = reinterpret_cast<CBaseY*>(pD); 12. printf("CBaseY* pY2 = %x\n", (int)pY2); 13. 14. // unrelated static_cast<> 15. CBaseY* pY3 = new CBaseY(); 16. printf("CBaseY* pY3 = %x\n", (int)pY3); // OK, even pY3 is just a "new CBaseY()" 17. CDerived* pD3 = static_cast<CDerived*>(pY3); 18. printf("CDerived* pD3 = %x\n", (int)pD3);
---------------------- output ---------------------------
CDerived* pD = 392fb8
CBaseY* pY1 = 392fbc
CDerived* pD1 = 392fb8
CBaseY* pY2 = 392fb8
CBaseY* pY3 = 390ff0
CDerived* pD3 = 390fec
Noted that when static_cast<>
-ing CDerived*
to CBaseY*
(line 5), the result is CDerived*
offset by 4. To know what static_cast<>
is actually doing, we have to take a look at the memory layout of CDerived
.Memory Layout of CDerived
CDerived
's memory layout contains two objects, CBaseX
and CBaseY
, and the compiler knows this. Therefore, when you cast CDerived*
to CBaseY*
, it adds the pointer by 4, and when you cast CBaseY
to CDerived
, it subtracts the pointer by 4. However, you can do this even if it is not a CDerived
(line 14-18) [1].Of course, the problem happens only if you have multiple inheritance.
static_cast<>
and reinterpret_cast<>
make no different if you are casting CDerived
to CBaseX
.Case 3: Casting back and forth between void*
Because any pointer can be cast tovoid*
, and void*
can be cast back to any pointer (true for both static_cast<>
and reinterpret_cast<>
), errors may occur if not handled carefully.
CDerived* pD = new CDerived();
printf("CDerived* pD = %x\n", (int)pD);
CBaseY* pY = pD; // OK, pY = pD + 4
printf("CBaseY* pY = %x\n", (int)pY);
void* pV1 = pY; // OK, pV = pY
printf("void* pV1 = %x\n", (int)pV1);
// pD2 = pY, but we expect pD2 = pY - 4
CDerived* pD2 = static_cast<CDerived*>(pV1);
printf("CDerived* pD2 = %x\n", (int)pD2);
// System crash
// pD2->bar();
---------------------- output ---------------------------
CDerived* pD = 392fb8
CBaseY* pY = 392fbc
void* pV1 = 392fbc
CDerived* pD2 = 392fbc
Once we have cast the pointer to void*
, we can't cast it back to the original class easily. In the above example, the only way to get back a CDerived*
from a void*
is to cast it to a CBaseY*
and then to CDerived*
. But if we are not sure whether it is CBaseY*
or CDerived*
, then we have to use dynamic_cast<>
or typeid
[2].Footnote
dynamic_cast<>
, on the other hand, can guard against casting a genericCBaseY*
toCDerived*
.dynamic_cast<>
requires the classes to be "polymorphic", i.e., contains "virtual" function, and hence can't bevoid*
.
6 comments:
It's not my first time to visit this web page, i am browsing this web page dailly and obtain fastidious data from here daily.
My web-site: atlaslm.com
To give your cake that special finish you could use one of the cake topper sets available
which tend to consist of building blocks, the slingshots and the characters.
The other day, I was talking with an acquaintance who stated
that "There are many issues in modern society that bother me, I feel that everybody is a zombie, people seem to be blind to what actually happening around them, newspaper headlines are full of celebrity nonsense, everything seems designed to distract people from the real world, everything seems so detached. What's nice about About Angry birds is that it has a very basic idea and concept.
Check out my blog post; angry birds online spielen
It's not my first time to pay a quick visit this website, i am visiting this site dailly and take nice facts from here everyday.
my web blog - http://www.biotechnologyreview.net/ar/food-biotechnology.php
Bring your favorite magazines to the i - Phone with an i - Phone app.
Aamir Khan and Amitabh Bachchan had a rough battle,
when the movies related to them were released at the same time.
As a consequence it can be contended the media is directing many persons astray moving away from what should be its aim of
presenting discerning news and analytic thinking of pressing topics for this celebrity frippery.
My web blog ... latest celeb news
Hello, I read your blog on a regular basis. Your writing style is awesome, keep it up!
Here is my web page ... http://hardbodytube.com/
Make a list of your nutrition chart involving juice and fruits at the top
followed by green vegetables and milk products. Then you'll have no trouble motivating yourself to do it. ' Being physically active can promote good mental health and
help you to manage stress, anxiety and depression.
Here is my web blog - fitness tips abs
Post a Comment