reinterpret_cast<>() v. static_cast<>()

Discussion in 'C++' started by Scott Brady Drummonds, Jan 13, 2004.

  1. Hi, everyone,

    I've checked a couple of on-line resources and am unable to determine how
    reinterpret_cast<> is different from static_cast<>. They both seem to
    perform a compile-time casting of one type to another. However, I'm certain
    that there is something else that is happening.

    Can someone explain the difference or recommend an online site that can
    explain it to me?

    Thanks,
    Scott

    --
    Remove ".nospam" from the user ID in my e-mail to reply via e-mail.
     
    Scott Brady Drummonds, Jan 13, 2004
    #1
    1. Advertising

  2. Scott Brady Drummonds

    David Harmon Guest

    On Tue, 13 Jan 2004 13:53:48 -0800 in comp.lang.c++, "Scott Brady
    Drummonds" <> was alleged to have
    written:
    >Hi, everyone,
    >
    >I've checked a couple of on-line resources and am unable to determine how
    >reinterpret_cast<> is different from static_cast<>. They both seem to
    >perform a compile-time casting of one type to another. However, I'm certain
    >that there is something else that is happening.


    static_cast<> uses sensible, well-defined conversions. For example, the
    integer 10 would be converted to the double 10.0.

    reinterpret_cast<> just looks at the bits in memory in as if they were
    the encoding as a different type. For example, the integer 10 would
    look like some number who-knows-what as a double.
     
    David Harmon, Jan 13, 2004
    #2
    1. Advertising

  3. Scott Brady Drummonds

    Ron Natalie Guest

    "Scott Brady Drummonds" <> wrote in message news:bu1pdd$1po$...
    > Hi, everyone,
    >
    > I've checked a couple of on-line resources and am unable to determine how
    > reinterpret_cast<> is different from static_cast<>. They both seem to
    > perform a compile-time casting of one type to another. However, I'm certain
    > that there is something else that is happening.


    There are two major differences:
    1. static_cast won't convert certain types (you'll get a compile error).
    2. when both will perform the conversion, the nature of the conversion is different.

    Static_cast has two uses. First it will force a conversion that could have happened implicitly.
    For example:
    double value = 1.45;
    double remainder = value - static_cast<int>(value);

    Here we force a conversion that could be done implicitly with an extra temporary variable.
    The other use, is to reverse a defined conversion. If there is a valid forward conversion,
    in most cases you can reverse it with a static cast.

    struct Base {
    };
    struct Derived : Base {
    };

    Derived d;
    Base* bp = &d; // implicit conversion.
    Derived* dp = static_cast<Derived*>(bp); // invert valid conversion.

    A reinterpret cast pretty much says, treat these bits as another type. Its results are implementation
    specific in most cases. You can do things like:
    char* foo = ...

    unsigned char* foo = reinterpret_cast<unsigned char*>(foo); // force type change!

    Needless to say you should think twice in general before doing this. The compiler will
    refuse to do the static_cast of the above types because they are unrelated (no conversion
    defined in either direction).

    Now here's a case where they both casts will do something different (in many circumstances):

    struct BaseA {
    char a;
    };
    struct BaseB {
    char b;
    };
    struct Derived : BaseA, BaseB {
    };

    Derived d;
    BaseB* bp = static_cast<BaseB*>(&d); // valid: bp now points to BaseB subobject of d
    BaseB* rp = reinterpret_cast<BaseB*>(&d); // probably not valid, could result in rp pointing at
    // the BaseA memory in d but with the BaseB* type.
     
    Ron Natalie, Jan 13, 2004
    #3
  4. Scott Brady Drummonds

    AngleWyrm Guest

    "Scott Brady Drummonds" <> wrote in
    message news:bu1pdd$1po$...
    > Can someone explain the difference or recommend an online site that can
    > explain it to me?


    static_cast<> is for related casts; (float->int, int->enum, etc).
    reinterpret_cast<> is for totally unrelated type conversions (which
    shouldn't usually be done). For example:

    // Converting a hex number to a device port
    IO_device* myDevicePort = reinterpret_cast<IO_device*>(0XFF00) // device at
    0xFF00
     
    AngleWyrm, Jan 14, 2004
    #4
  5. "Ron Natalie" <> wrote in message
    news:40046e6f$0$62140$...
    >
    > "Scott Brady Drummonds" <> wrote in

    message news:bu1pdd$1po$...
    > > Hi, everyone,
    > >
    > > I've checked a couple of on-line resources and am unable to determine

    how
    > > reinterpret_cast<> is different from static_cast<>.

    ....
    > There are two major differences:
    > 1. static_cast won't convert certain types (you'll get a compile

    error).
    > 2. when both will perform the conversion, the nature of the

    conversion is different.
    ....

    Thank you so much, Ron, for the detailed description!

    Scott
     
    Scott Brady Drummonds, Jan 14, 2004
    #5
  6. Scott Brady Drummonds

    forums_mp Guest

    "Scott Brady Drummonds" <> wrote in message news:<bu1pdd$1po$>...
    > Hi, everyone,
    >
    > I've checked a couple of on-line resources and am unable to determine how
    > reinterpret_cast<> is different from static_cast<>. They both seem to
    > perform a compile-time casting of one type to another. However, I'm certain
    > that there is something else that is happening.
    >
    > Can someone explain the difference or recommend an online site that can
    > explain it to me?
    >
    > Thanks,
    > Scott


    Interestingly enough I just went through the process of laying some
    ground rules on the use of the C++ casts.
    A synopsis of what I was able to deduce - of course the experts will
    correct me if I'm mistaken

    ---------
    reinterpret_cast is ONLY for pointers, of the same constness. You can
    cast a char* to an unsigned char* or any other * with
    reinterpret_cast, but you can't cast off constness with reinterpret
    cast.

    const_cast is to cast off constness. If you have a const char* and
    ABSOLUTELY MUST get rid of its constness and KNOW FOR A FACT that that
    operation is safe AND you can't just make a new copy of the buffer ...
    then const_cast is your tool.

    static_cast is for casting a base class to a derived class. No
    runtime type checking is performed so this seems/is inherently
    dangerous, but sometimes if you are stuck with a bad design ...
    unavoidable. You can also cast an int to an enum using static cast,
    as well as a few other things.

    dynamic_cast is a "safe" way to cast a base class to a derived class,
    but it requires you to include type information in your build. if at
    runtime, if the cast can't be performed, then the cast returns 0,
    otherwise the cast succeeds and you continue your program.

    ---------

    Along the same lines I have a question.
    Notwithstanding the C++ casts are limited in scope which in my view
    implies (no proof though) that they are safer than the C variant,
    whats the 'real' gain over the C cast? A question that seems to crop
    up with no reasonable answer on my part. I suspect in the grand
    scheme of things casting it's low level bit twiddling on both parts
    (C/C++)

    ----------
     
    forums_mp, Jan 15, 2004
    #6
  7. Scott Brady Drummonds

    Cy Edmunds Guest

    [snip]

    > Along the same lines I have a question.
    > Notwithstanding the C++ casts are limited in scope which in my view
    > implies (no proof though) that they are safer than the C variant,
    > whats the 'real' gain over the C cast? A question that seems to crop
    > up with no reasonable answer on my part. I suspect in the grand
    > scheme of things casting it's low level bit twiddling on both parts
    > (C/C++)
    >
    > ----------


    C casts are simply too powerful (about the same as the dreaded
    reinterpret_cast). For instance in some cases you can, with a single typo,
    cast one pointer type to a completely different pointer type when all you
    meant to do was cast away constness. If you make that mistake with a
    const_cast you will get a compile time error.

    --
    Cy
    http://home.rochester.rr.com/cyhome/
     
    Cy Edmunds, Jan 15, 2004
    #7
  8. Scott Brady Drummonds

    Ron Natalie Guest

    "forums_mp" <> wrote in message news:...

    >
    > static_cast is for casting a base class to a derived class. No
    > runtime type checking is performed so this seems/is inherently
    > dangerous, but sometimes if you are stuck with a bad design ...
    > unavoidable. You can also cast an int to an enum using static cast,
    > as well as a few other things.


    This is incomplete. Static cast has lots of other use other than casting
    from base to derived.

    > dynamic_cast is a "safe" way to cast a base class to a derived class,
    > but it requires you to include type information in your build. if at
    > runtime, if the cast can't be performed, then the cast returns 0,
    > otherwise the cast succeeds and you continue your program.


    No, it requires the pointer casted from to be a polymorphic class
    in most (but not all cases). If that's what you mean by "including
    type information" in your build, fine, but you'd be better off using
    the proper terminology.
    >
    > Along the same lines I have a question.
    > Notwithstanding the C++ casts are limited in scope which in my view
    > implies (no proof though) that they are safer than the C variant,
    > whats the 'real' gain over the C cast? A question that seems to crop
    > up with no reasonable answer on my part. I suspect in the grand
    > scheme of things casting it's low level bit twiddling on both parts
    > (C/C++)


    First, the fact that they are limited in scope, means that the compiler will
    check inadvertent errors like changing the type when all you mean to do
    is change the const etc.... Further as I pointed out in my original response,
    the C++ static_, dynamic_ and reinterpret_ casts DO DIFFERENT THINGS
    when presented the same casting arguments. The C-Style cast will do combinations
    of static, const and reinterpret (as well as a conversion for which there is no
    C++ equivalent). Yes, if you think about it, you can determine which one it
    will do, but that is frequently fraught with perils.
     
    Ron Natalie, Jan 15, 2004
    #8
  9. Scott Brady Drummonds

    Jerry Coffin Guest

    In article <>,
    says...

    [ ... ]

    > reinterpret_cast is ONLY for pointers, of the same constness. You can
    > cast a char* to an unsigned char* or any other * with
    > reinterpret_cast, but you can't cast off constness with reinterpret
    > cast.


    IIRC, reinterpret_cast can be used on references as well as pointers.

    > const_cast is to cast off constness. If you have a const char* and
    > ABSOLUTELY MUST get rid of its constness and KNOW FOR A FACT that that
    > operation is safe AND you can't just make a new copy of the buffer ...
    > then const_cast is your tool.


    const_cast can also be used to modify volatility.

    > static_cast is for casting a base class to a derived class. No
    > runtime type checking is performed so this seems/is inherently
    > dangerous, but sometimes if you are stuck with a bad design ...
    > unavoidable. You can also cast an int to an enum using static cast,
    > as well as a few other things.


    You should almost never use static_cast to cast between different types
    in the same hierarchy -- moving up the hierarchy can be done implicitly,
    and down the hierarchy should normally use dynamic_cast. static_cast
    should normally be used for things like floating->integer.

    > dynamic_cast is a "safe" way to cast a base class to a derived class,
    > but it requires you to include type information in your build. if at
    > runtime, if the cast can't be performed, then the cast returns 0,
    > otherwise the cast succeeds and you continue your program.


    That's how it works for pointers. For references, dynamic_cast succeeds
    or throws and exception.

    > Along the same lines I have a question.
    > Notwithstanding the C++ casts are limited in scope which in my view
    > implies (no proof though) that they are safer than the C variant,
    > whats the 'real' gain over the C cast? A question that seems to crop
    > up with no reasonable answer on my part. I suspect in the grand
    > scheme of things casting it's low level bit twiddling on both parts
    > (C/C++)


    Anything that tries to talk about "the 'real' gain" is almost certain to
    be wrong. There are a number of improvements. dynamic_cast provides a
    capability that a C-style cast simply doesn't provide at all.
    const_cast provides a capability that a C-style cast could provide, but
    is safer since it won't let you accidentally cast to some type that's
    totally unrelated to the original type or something like that. From an
    entirely different sort of viewpoint, it's essentially impossible to
    grep for C-style casts, but trivial to do so for the new C++ casts.

    --
    Later,
    Jerry.

    The universe is a figment of its own imagination.
     
    Jerry Coffin, Jan 18, 2004
    #9
  10. Scott Brady Drummonds

    Old Wolf Guest

    > > dynamic_cast is a "safe" way to cast a base class to a derived class,
    > > but it requires you to include type information in your build. if at
    > > runtime, if the cast can't be performed, then the cast returns 0,
    > > otherwise the cast succeeds and you continue your program.

    >
    > That's how it works for pointers. For references, dynamic_cast succeeds
    > or throws and exception.


    Is this UB:
    class Base { /* ... */ };
    class Derived: public Base { public: int bar; };

    void foo(Base *b)
    {
    try {
    dynamic_cast<Derived *>(b)->bar = 3;
    }
    catch(...) {
    do_error("non-derived object passed");
    }
    }

    I had previously assumed that this was a safe technique because
    the dynamic_cast would throw. But if this is not the case, then
    there is UB because of the 0-dereference (it might not even
    throw an exception at all).
     
    Old Wolf, Jan 19, 2004
    #10
  11. Scott Brady Drummonds

    Ron Natalie Guest

    "Old Wolf" <> wrote in message news:...
    > I had previously assumed that this was a safe technique because
    > the dynamic_cast would throw. But if this is not the case, then
    > there is UB because of the 0-dereference (it might not even
    > throw an exception at all).


    Correct.
     
    Ron Natalie, Jan 19, 2004
    #11
  12. "Old Wolf" <> wrote in message
    news:...
    > > > dynamic_cast is a "safe" way to cast a base class to a derived class,
    > > > but it requires you to include type information in your build. if at
    > > > runtime, if the cast can't be performed, then the cast returns 0,
    > > > otherwise the cast succeeds and you continue your program.

    > >
    > > That's how it works for pointers. For references, dynamic_cast succeeds
    > > or throws and exception.

    >
    > Is this UB:
    > class Base { /* ... */ };
    > class Derived: public Base { public: int bar; };
    >
    > void foo(Base *b)
    > {
    > try {
    > dynamic_cast<Derived *>(b)->bar = 3;
    > }
    > catch(...) {
    > do_error("non-derived object passed");
    > }
    > }
    >
    > I had previously assumed that this was a safe technique because
    > the dynamic_cast would throw. But if this is not the case, then
    > there is UB because of the 0-dereference (it might not even
    > throw an exception at all).


    It can never throw an exception (except in the sense that theoretically it
    could
    because deref. 0 is UB).

    You want:

    dynamic_cast<Derived&>(*b).bar = 3;

    or replace the whole thing with:

    if( Dervived* dp = dynamic_cast<Derived*>(b))
    {
    dp->bar = 3;
    }
    else
    do_error(.....);

    P.S. unless you add one or more virtual methods
    to Base dynamic_cast will
    not work for you anyway - it will just do the same as
    static_cast which will NEVER return null (unless b is).
     
    Nick Hounsome, Jan 20, 2004
    #12
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Kobe
    Replies:
    3
    Views:
    618
    Tomás
    Feb 15, 2006
  2. Peter
    Replies:
    7
    Views:
    510
    bjarne
    Aug 9, 2006
  3. Lucy Ludmiller

    reinterpret_cast or static_cast ?

    Lucy Ludmiller, Sep 3, 2006, in forum: C++
    Replies:
    2
    Views:
    440
    dasjotre
    Sep 7, 2006
  4. Pallav singh
    Replies:
    5
    Views:
    1,012
    James Kanze
    Dec 6, 2010
  5. Alex Vinokur
    Replies:
    1
    Views:
    605
Loading...

Share This Page