C ++ distinction between reinterpreted and c style

code:

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

      

Output:

Same!

I wonder what the difference is between the two casting methods. Also if you can point out (with examples) the difference between static_cast, dynamic_cast, and other types of casting you know (i.e., stay low and as close to assembly language as possible).

static_cast
dynamic_cast
const_cast
reinterpret_cast
C-style cast (type)value
Function-style cast type(value)

      

Thank.

Please read PS I know from the above example that reinterpret_cast assigns an int pointer to the address of keyStr [29] In the assembly to be translated to:

lea eax, [keyStr+1D]
mov [reCast], eax

      

Thus, a reinterpret_cast, at a low level, is not dangerous at all since it does not alter the original data.

I wanted to know how other casting methods behave at a low level. So, for example, an object, at a low level, is just a variable that contains an address. And the type, if that object is how the compiler then interprets that address and how it offsets it (which is exactly what I'm not interested in, in assembly, I could care less if this variable contains a value, pointer, or object (i.e. another pointer)). Another thing that may be the same is the difference between int and int * or unsigned int and int; all 4 declarations generate the same build instruction. (push value) or (sub esp- (int length) and mov esp, value) Hope this clears up the question and why I marked it "low level code" and "build"

PS In this program I am trying to create, I dont care about portability or other high level stuff. I try to be as low as possible and as close to assembler as possible. This means that for this program memory is just memory (that is, 0 and 1 bits) and the types are not important (for example, I don't care if the mem: 0x123 address is of type "int" or "float", it's just " data ")

+3


source to share


4 answers


reinterpret_cast

and const_cast

are ways to get around the C ++ type system. As you noted for reinterpret_cast

, this usually means little or no assembly code.

static_cast

mostly refers to a C ++ type system. It can convert a number from one type to another, or call a constructor or call a conversion function. Or, for a derived base conversion, this might involve adding byte offsets and / or lookups to the vtable. static_cast

can also bend system type 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 the member. They are probably irrelevant, but they static_cast

make things more or less similar to class pointer conversions.

dynamic_cast

more strictly adheres to the C ++ type system. In its useful form, it checks at runtime if a pointer / reference actually points / refers to an object of the specified type. It usually calls the magic library function under the covers.



A function-style with one argument has the same effect as a C-style cast (With more than one argument, a function call must be a call to the class's constructor.) A C-style cast does the first thing that makes sense from the following list:

  • a const_cast

  • a static_cast

  • a static_cast

    and then aconst_cast

  • a reinterpret_cast

    or
  • a reinterpret_cast

    and then aconst_cast

The only exception is that C-style casts can ignore private and protected inheritance relationships between classes, pretending to have a common inheritance relationship.

C-style styles are generally not preferred in C ++ as they are less specific about what you want.

+3


source


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

It's not as dangerous as the c-style, which discards the const / volatileness of the value in question, as well as any information about what it points to.

Understanding these operations in assembler is a bit pointless. These are not assembly constructs. These are C ++ language constructs that work something like this:

static_cast

- Effectively it converts an object from one type to another. Note that this may change the meaning ( static_cast<float>(1)

does not have the same bit pattern, e.g. 1).



dynamic_cast

- if this object can be viewed as another type through inheritance then treat it as such, otherwise render it as zero. This will not change the value of the pointer, but it will safely change the compilers' representation.

const_cast

- drop qualifiers const

(or volatile

), which is not always a good idea, since it allows you to destroy data that, in the client's opinion, was safe.

reinterpret_cast

- treat the bit pattern as something different from what the compiler thought. Commonly used for pointers and hopefully rarely. reinterpret_cast

Typing int in is float

unlikely to be a good idea, but it will keep the same bit pattern.

c-style-cast - Take a bit of the pattern, completely forget that you know about it, and treat it like something else. A dangerous and almost invisible combination static_cast

, reinterpret_cast

and const_cast

. This is not considered a good idea in C ++ code because it is difficult to find in the overview and because it is not specific about what is going on.

0


source


In your example, there is no difference between a C style application and a reinterpret_cast because you are casting between unbound pointers and there is no constant. If you had const

one side, the reinterpret_cast would suffocate when a C style cast would make a const_cast under the hood.

The danger with reinterpret_cast (or C style casts) is that it allows casting between unrelated objects. In your example, you run the risk of getting an error when dereferencing reCast

(or reCast2

) because you are trying to access an inconsistent integer.

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

  • when compiling, C style casting will always be allowed (almost) - I don't know of examples where it will give a compilation error, but may be compiler dependent
  • reinterpret_cast will resolve in the same cases if there is no constant change
  • const_cast can only change a constant
  • static_cast will resolve (only at compile time) between related types

This whole addition was added to C ++ to avoid capturing all C-style modes and to allow some compilation and runtime checks. - dynamic_cast will only be resolved at compile time between related types and , the compiler will inject code to manipulate validity at runtime

0


source


The difference is that when using C style in a C ++ file, in some cases you will get an error and will not be able to compile. reinterpret_cast

solves such cases. Something like - you say to the compiler, "I know this is an incompatible casting, but let it be okay." C ++ is much more limited than C for things like casting.

-1


source







All Articles