简体   繁体   English

C++ 重新解释强制转换和 C 风格强制转换之间的区别

[英]c++ difference between reinterpret cast and c style cast

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 Thing!一样!

I wonder what's the difference between the two casting methods.我想知道这两种铸造方法有什么区别。 Also if you could specify ( with examples ) difference between static_cast, dynamic_cast, and other types of casting you know ( ie while staying as low level and as close to assembly language as possible ).此外,如果您可以指定(用示例)static_cast、dynamic_cast 和您所知道的其他类型的转换之间的区别(即,同时保持尽可能低的级别并尽可能接近汇编语言)。

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

Thanks.谢谢。

Please read the PS I know from the example above that reinterpret_cast assigns to the int pointer the address of keyStr[29] In assembly that would translate into:请阅读我从上面的示例中知道的 PS,reinterpret_cast 将 keyStr[29] 的地址分配给 int 指针,在汇编中将转换为:

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

So in other words reinterpret_cast, in a low level prospective, is not dangerous at all as it does not modify the original data.因此,换句话说 reinterpret_cast,在低级别的前景中,根本没有危险,因为它不会修改原始数据。

I wanted to know how the other casting methods behave in a low level way.我想知道其他铸造方法如何以低级方式运行。 So, for example, an object, in a low level way, is just a variable which holds an address.因此,例如,在低级方式中,对象只是一个保存地址的变量。 And the type if that object is how the compiler then interprets that address and how it offsets it.( this is exactly what I'm not interested in, in assembly, i could care less if that variable holds a value, a pointer or an object ( ie another pointer ) ).如果该对象的类型是编译器如何解释该地址以及它如何偏移它。(这正是我不感兴趣的,在汇编中,如果该变量包含值、指针或对象(即另一个指针))。 Another thing that could be just the same, is the difference between int and int* or unsigned int and int;另一件可能相同的事情是 int 和 int* 或 unsigned int 和 int 之间的区别; all 4 declarations generate the same assembly instruction.所有 4 个声明都生成相同的汇编指令。 ( push value ) or (sub esp-(length of int) && mov esp, value) I hope this clarifies the question and why I tagged it "low-level-code" and "assembly" ( push value ) 或 (sub esp-(length of int) && mov esp, value) 我希望这能澄清问题以及我为什么将其标记为“低级代码”和“程序集”

PS In this program I'm trying to create I don't care for non portability or other high level stuff. PS 在这个程序中,我正在尝试创建我不关心不可移植性或其他高级别的东西。 I'm trying to be as low level as possible and as close to assembly language as possible.我正在尝试尽可能低级并尽可能接近汇编语言。 That means that, for this program, memory is just memory ( ie 0 and 1 bits ) and types are not important ( eg I don't care if mem address: 0x123 is an "int" type or "float" type, it's just "data")这意味着,对于这个程序,内存只是内存(即 0 和 1 位),类型并不重要(例如,我不在乎内存地址:0x123 是“int”类型还是“float”类型,它只是“数据”)

reinterpret_cast and const_cast are ways of getting around the C++ type system. reinterpret_castconst_cast是绕过 C++ 类型系统的方法。 As you noted for reinterpret_cast , this usually translates to little or no assembly code.正如您在reinterpret_cast指出的那样,这通常转化为很少或没有汇编代码。

static_cast mostly respects the C++ type system. static_cast主要尊重 C++ 类型系统。 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.或者对于派生到基类的转换,它可能涉及将字节偏移量和/或查找添加到 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. static_cast还可以通过将指针或引用从非虚拟基类型“向下转换”为派生类型(可能减去字节偏移量)来弯曲类型系统的规则。

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.他们在这里可能不是重点,但是static_cast对他们做的事情或多或少类似于类指针转换。

dynamic_cast respects the C++ type system even more strictly. dynamic_cast更加严格地尊重 C++ 类型系统。 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.带有一个参数的函数式转换与 C 式转换具有完全相同的效果。 (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: (如果有多个参数,函数样式转换必须是使用类构造函数的临时初始化。)C 样式转换执行以下列表中的第一件事:

  • a const_cast一个const_cast
  • a static_cast一个static_cast
  • a static_cast and then a const_cast一个static_cast然后一个const_cast
  • a reinterpret_cast , or一个reinterpret_cast ,或
  • a reinterpret_cast and then a const_cast一个reinterpret_cast然后一个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 风格的转换可以忽略类之间的私有和受保护的继承关系,假装它们具有公共继承关系。

C-style casts are usually not preferred in C++ because it's less specific about what you want to happen. C 风格的强制转换在 C++ 中通常不是首选,因为它对你想要发生的事情不太具体。

In what way do you mean "not dangerous"?你是什​​么意思“不危险”? reinterpret_cast is incredibly dangerous. reinterpret_cast 非常危险。 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.它不像 c 样式转换那样危险,它会丢弃所讨论值的常量/易失性以及有关它所指向内容的任何信息。

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:它们是 C++ 语言结构,其工作原理如下:

static_cast - Effectively this converts an object from one type to another. static_cast - 这有效地将对象从一种类型转换为另一种类型。 Note this can change the value ( static_cast<float>(1) doesn't have the same bit pattern as 1 for instance).请注意,这可以更改值(例如, static_cast<float>(1)没有与 1 相同的位模式)。

dynamic_cast - if this object can be considered to be another type through inheritance, then treat it as such, otherwise render it as zero. dynamic_cast - 如果可以通过继承将此对象视为另一种类型,则将其视为此类,否则将其视为零。 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. const_cast - 丢弃const (或volatile )限定符,这通常不是一个好主意,因为它允许您销毁客户端认为安全的数据。

reinterpret_cast - treat the bit pattern as meaning something different to what the compiler thought it did. reinterpret_cast - 将位模式视为与编译器认为的不同的含义。 Usually used for pointers and hopefully rarely.通常用于指针,希望很少使用。 reinterpret_cast ing an int into a float is unlikely to be a good idea, but it will keep the same bit pattern. reinterpret_cast将 int 转换为float不太可能是一个好主意,但它会保持相同的位模式。

c-style-cast - Take the bit pattern, forget completely what you know about it, and treat it as something else. c-style-cast - 采用位模式,完全忘记你对它的了解,并将其视为其他东西。 A dangerous and almost invisible combination of static_cast , reinterpret_cast and const_cast . static_castreinterpret_castconst_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.它在 C++ 代码中不被认为是一个好主意,因为它很难在审查中发现,并且因为它没有具体说明正在发生的事情。

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 .在您的示例中,C 样式转换和 reinterpret_cast 之间没有区别,因为您在不相关的指针之间进行转换,并且没有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.如果你在一个部件上有一个const ,那么当 C 风格的强制转换会在底层完成 const_cast 时,reinterpret_cast 就会窒息。

The danger of the reinterpret_cast (or of the C style cast) is precisely that it allows casting between unrelated objects. reinterpret_cast(或 C 风格的转换)的危险恰恰在于它允许在不相关的对象之间进行转换。 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.在您的示例中,您很有可能在取消引用reCast (或reCast2 )时收到错误,因为您尝试访问未对齐的整数。

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在编译时(几乎)总是允许使用 C 样式转换 - 我不知道它会给出编译错误的示例,但它可能依赖于编译器
  • a reinterpret_cast will be allowed in same cases provided there is no constness change如果没有常量更改,在相同情况下将允许 reinterpret_cast
  • a const_cast can only change constness const_cast 只能改变常量性
  • a static_cast will only be allowed (at compile time) between related types仅允许(在编译时)在相关类型之间使用 static_cast

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.所有这些强制转换都是在 C++ 中添加的,以避免 C 风格强制转换的全部模式,并允许进行一些编译和运行时检查。 - 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 -一个dynamic_cast的将只在相关类型编译器将在运行时插入代码,以控制有效性之间的编译时被允许

The difference is that with C-style cast in C++ file in some cases you will get error and cannot compile.不同之处在于,在某些情况下,在 C++ 文件中使用 C 风格的强制转换会出错并且无法编译。 reinterpret_cast solves such cases. reinterpret_cast解决了这种情况。 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. C++ 在诸如强制转换之类的事情上比 C 受到更多的限制。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM