c++ difference between reinterpret cast and c style cast

后端 未结 4 1272
栀梦
栀梦 2021-02-10 17:38

Code:

char keyStr[50]={ 0x5F, 0x80 /* bla bla */ };
uint32_t* reCast  = reinterpret_cast< uint32_t* >( &keyStr[29] );
uint32_t* reCast2 = ( uint32_t* )         


        
相关标签:
4条回答
  • 2021-02-10 17:53

    The difference is that with C-style cast in C++ file in some cases you will get error and cannot compile. reinterpret_cast solves such cases. Something like - you tell to compiler: "I know it is incompatible casting, but let assume it is ok". C++ is far more restricted than C for such things like casting.

    0 讨论(0)
  • 2021-02-10 18:00

    In your example there are no differences between the C style cast and the reinterpret_cast, because you are casting between unrelated pointers, and there is no constness. If you have had a const on one part, reinterpret_cast would have choked when C style cast would have done the const_cast under the hood.

    The danger of the reinterpret_cast (or of the C style cast) is precisely that it allows casting between unrelated objects. In your example, you have a high risk that when you dereference reCast (or reCast2) you get an error because you try to access a misaligned integer.

    At low level, all casting have same effect (if they are valid) : they will all give the value or address. The main difference is :

    • a C style cast will (almost) always be allowed at compile time - I do not know examples where it will give a compile error but it might be compiler dependant
    • a reinterpret_cast will be allowed in same cases provided there is no constness change
    • a const_cast can only change constness
    • a static_cast will only be allowed (at compile time) between related types

    All this cast were added in C++ to avoid the catch all mode of C style cast and allow for some compile and run time checks. - a dynamic_cast will only be allowed at compile time between related types and the compiler will insert code to control validity at run time

    0 讨论(0)
  • 2021-02-10 18:04

    In what way do you mean "not dangerous"? reinterpret_cast is incredibly dangerous. It tells the compiler it is safe to ignore what it thinks it knows about the value.

    It's not as dangerous as a c-style cast which throws away the const/volatileness of the value in question as well as any information about what it is pointing to.

    Understanding these operations in assembly language is a bit pointless. They aren't assembly language constructs. They're C++ language constructs, that work something as follows:

    static_cast - Effectively this converts an object from one type to another. Note this can change the value (static_cast<float>(1) doesn't have the same bit pattern as 1 for instance).

    dynamic_cast - if this object can be considered to be another type through inheritance, then treat it as such, otherwise render it as zero. This won't change the value of a pointer but it does safely change the compilers view of it.

    const_cast - throw away const (or volatile) qualifiers, which is not often a good idea as it allows you to destroy data the client thought was safe.

    reinterpret_cast - treat the bit pattern as meaning something different to what the compiler thought it did. Usually used for pointers and hopefully rarely. reinterpret_casting an int into a float is unlikely to be a good idea, but it will keep the same bit pattern.

    c-style-cast - Take the bit pattern, forget completely what you know about it, and treat it as something else. A dangerous and almost invisible combination of static_cast, reinterpret_cast and const_cast. It's not considered a good idea in C++ code because it's hard to spot in a review, and because it is not specific about what is happening.

    0 讨论(0)
  • 2021-02-10 18:06

    reinterpret_cast and const_cast are ways of getting around the C++ type system. As you noted for reinterpret_cast, this usually translates to little or no assembly code.

    static_cast mostly respects the C++ type system. It could convert a number from one type to another, or call a constructor, or call a conversion function. Or for a derived-to-base conversion, it might involve adding byte offsets and/or lookups into a vtable. static_cast can also bend the type system's rules by "downcasting" a pointer or reference from a non-virtual base type to a derived type, possibly subtracting a byte offset.

    And then there are pointers-to-member. They're probably beside the point here, but static_cast does things to them more or less analogous to class pointer conversions.

    dynamic_cast respects the C++ type system even more strictly. In its useful form, it checks at runtime whether or not a pointer/reference actually points/refers to an object of the specified type. It typically calls a magic library function under the covers.

    A function-style cast with one argument has exactly the same effect as a C-style cast. (With more than one argument, a function-style cast must be a temporary initialization using a class constructor.) A C-style cast does the first thing that makes sense out of the following list:

    • a const_cast
    • a static_cast
    • a static_cast and then a const_cast
    • a reinterpret_cast, or
    • a reinterpret_cast and then a const_cast

    One exception: C-style casts can ignore private and protected inheritance relations between classes, pretending they have a public inheritance relation instead.

    C-style casts are usually not preferred in C++ because it's less specific about what you want to happen.

    0 讨论(0)
提交回复
热议问题