What static_cast<> is actually doing

Discussion in 'C++' started by Sanskruti, Feb 23, 2007.

  1. Sanskruti

    Sanskruti New Member

    Joined:
    Jan 7, 2007
    Messages:
    108
    Likes Received:
    18
    Trophy Points:
    0
    Occupation:
    Software Consultant
    Location:
    Mumbai, India
    Casts are used to convert the type of an object, expression, function argument, or return value to that of another type. Some conversions are performed automatically by the compiler without intervention by the programmer. These conversions are called implicit conversions. The standard C++ conversions and user-defined conversions are performed implicitly by the compiler where needed. Other conversions must be explicitly specified by the programmer and are appropriately called explicit conversions.

    Standard conversions are used for integral promotions , integral conversions , floating point conversions ,floating-integral conversions , arithmetic conversions , pointer conversions ,reference conversions and pointer-to-member conversions.

    You can provide a user-defined conversion from a class a to a class b by providing a constructor for b that takes an a as an argument:
    Code:
    b(const A& a)
    or by providing a class B with a conversion operator:
    Code:
    operator A( )
    When a type is needed for an expression that cannot be obtained through an implicit conversion or when more than one standard conversion creates an unknown situation, the programmer must explicitly specify the target type of the conversion.

    In C, an expression, expr, of type S can be cast to another type T in one of the following ways.
    By using an explicit cast:

    (T) expr

    or by using a functional form:

    T(expr)

    We will refer to either of these constructs as the old C-style casts.

    The old C-style casts have several shortcomings. First, the syntax is the same for every casting operation. This means it is impossible for the compiler to tell the intended purpose of the cast. Is it a cast from a base class pointer to a derived class pointer. Does the cast remove the ``const-ness'' of the object? Or, is it a conversion of one type to a completely unrelated type? it is impossible to tell from the syntax. As a result, this makes the cast harder to comprehend, not only by humans, but also by compilers which are unable to detect improper casts.

    Another problem is that the C-style casts are hard to find. Parentheses with an identifier between them are used all over C++ programs. Perhaps the most serious problem with the old C-style cast is that it allows you to cast practically any type to any other type. Improper use of casts can lead to dangerous results. The old C-style casts have created a few holes in the C type system and have also been a souce of confusion for both programmers and compilers. Even in C++, the old C-style casts are retained for backwards compatibility. However, using the new C++ style casting operators will make your programs more readable, type-safe, less error-prone, and easier to maintain.

    Let us see why C-style cast has fallen out of favor.

    Consider the following code listing:

    Code:
    void *p=&x;
    int n=(int)p; //C-style cast 
    The C-style cast seems harmless at first sight. Yet, it has several potential dangers. First, it performs different operations in different contexts. For example, it may perform a safe int to double promotion, but it can also perform inherently dangerous operations such as casting void* to a numeric value . The programmer can't always tell from the source code if the cast is safe or inherently dangerous.

    C-style cast may perform multiple operations at once.

    In the following example, not only does it cast char * to unsigned char *, but it also removes the const qualifier at the same time:

    Code:
    const char *msg="don't touch!";
    unsigned char *p=(unsigned char*) msg; // intentional?

    New Cast Operators



    The new C++ casting operators are intended to provide a solution to the shortcomings of the old C-style casts by providing:

    • Improved syntax:- Casts have a clear, concise, although somewhat cumbersome syntax. This makes casts easier to understand, find, and maintain.
    • Improved semantics:- The intended meaning of a cast is no longer unclear. Knowing what the programmer intended the cast to do makes it possible for compilers to detect improper casting operations.
    • Type-safe conversions. Allow some casts to be performed safely at run-time. This will enable programmers to check whether a particular cast is successful or not.

    C++ introduces four new casting operators:



    • static_cast, to convert one type to another type;
    • const_cast, to cast away the ``const-ness'' or ``volatile-ness'' of a type;
    • dynamic_cast, for safe navigation of an inheritance hierarchy; and
    • reinterpret_cast, to perform type conversions on un-related types.

    All of the casting operators have the same syntax and are used in a manner similar to templates.In this article we are going to see in details how static_cast is actually working.

    For example, to perform a static_cast of ptr to a type T we write:

    Code:
     T* t = static_cast<T> (ptr);
    static_cast is the most general and is intended as a replacement for most C-style casts.

    The static_cast Operator



    The static_cast operator takes the form

    Code:
    static_cast<T> (expr)
    to convert the expression expr to type T. Such conversions rely on static (compile-time) type information. You may use static_cast to convert a base class pointer to a derived class pointer, perform arithmetic conversions, convert an int to an enum, convert a reference of type X& to another reference of type Y&, convert an object of type X to an object of type Y, and convert a pointer-to-member to another pointer-to-member within the same class hierarchy.

    Internally, static_casts are used by the compiler to perform implicit type conversions such as the standard conversions and user-defined conversions. In general, a complete type can be converted to another type so long as some conversion sequence is provided by the language.

    static_cast performs safe and relatively portable casts. For example, you use static_cast to explicitly document a cast that would otherwise take place automatically. Consider the following example:

    Code:
    bool b=true;
    int n=static_cast<int> (b);
    C++ automatically casts bool to int in this context so the use of static_cast in this case isn't necessary.In other contexts, static_cast is mandatory.

    For example, when you cast void* to a different pointer type, as in the following example:

    Code:
    int n=4;
    void *pv=&n;
    int pi2 = static_cast<int *> (pv); //mandatory
    static_cast uses the information available at compile time to perform the required type conversion. Therefore, the target and the source might not be identical in their binary representation. Consider a float to int conversion. The binary representation of the floating number 10.0 is quite different from the equivalent integer value of 10. static_cast performs the necessary adjustments when casting one to the other.

    One of the more common uses of static_cast is to perform arithmetic conversions, such as from int to double. For example, to avoid the truncation in the following computation:
    Code:
     int   total = 500;
    int   days  = 9;
    double rate = total/days;
    We can write:
    Code:
    double rate = static_cast<double>(total)/days;
    A static_cast may also be used to convert an integral type to an enumeration.

    Consider:
    Code:
    enum fruit {apple=0,orange,banana};
    int i  1 = 2; 
    fruit f1 = static_cast<fruit> (i1);
    The conversion results in an enumeration with the same value as the integral type provided the integral value is within the range of the enumeration. The conversion of an integral value that is not within the range of the enumeration is undefined.

    You may also use static_cast to convert any expression to a void, in which case the value of the expression is discarded.

    One interesting side effect of the old C-style casts, was to gain access to a private base class of a derived class.

    Consider this hierarchy:

    Code:
     
    class Base
    {
      public:
    	Base() : _data(999) {}
    	int  Data() const {return _data;}
      private:
    	int _data;
    };
    
    class Derived : private Base
    {
      public:
    	Derived () : Base() {}
    }; 
    
    Derived* d1 = new Derived;  
    Normally, you should not be able to access Data() through the pointer d1. However, using an old C-style cast, we can:

    Code:
    Base* b1 = (Base*) d1;
    int i = b1->Data(); // works!
    The good news is that if you attempt to use static_cast:

    Code:
    Base* b1 = static_cast<Base*>(d1);
    the compiler will correctly report that Base is inaccessible because it is a private base class.
     
  2. ronop667

    ronop667 New Member

    Joined:
    Feb 25, 2007
    Messages:
    1
    Likes Received:
    0
    Trophy Points:
    0
    Interesting article.
    two small points:
    1 I don't understand why the comments on C casts. Of course can not distinguish a derived class from a base class, there are no classes in C. Why would C want such restrictions?
    2 Integral is a part of calculus. Integer is the name of the type.
     
  3. shabbir

    shabbir Administrator Staff Member

    Joined:
    Jul 12, 2004
    Messages:
    15,375
    Likes Received:
    388
    Trophy Points:
    83
    Casting for structs is also valid.
    As what I get from this is integral means non floating point numbers like short, int, long ....
     
  4. rashida.par

    rashida.par New Member

    Joined:
    Feb 14, 2008
    Messages:
    21
    Likes Received:
    1
    Trophy Points:
    0
  5. sabharwal81

    sabharwal81 New Member

    Joined:
    Nov 20, 2009
    Messages:
    1
    Likes Received:
    0
    Trophy Points:
    0
    just read this article "What static_cast<> is actually doing ". want i really wanted to know is what static_cast does at memory level. what all pointer manipulations it does so as to cast one kind to another.
     
  6. BRIJESH SINGH

    BRIJESH SINGH New Member

    Joined:
    Nov 3, 2009
    Messages:
    1
    Likes Received:
    0
    Trophy Points:
    0
    that's is the best site for helping to understanding the programing.
     

Share This Page

  1. This site uses cookies to help personalise content, tailor your experience and to keep you logged in if you register.
    By continuing to use this site, you are consenting to our use of cookies.
    Dismiss Notice