Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/137.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 为什么';对于相同大小类型之间的强制转换,是否重新解释强制复制?_C++_Casting_Binary_Copy_Reinterpret Cast - Fatal编程技术网

C++ 为什么';对于相同大小类型之间的强制转换,是否重新解释强制复制?

C++ 为什么';对于相同大小类型之间的强制转换,是否重新解释强制复制?,c++,casting,binary,copy,reinterpret-cast,C++,Casting,Binary,Copy,Reinterpret Cast,根据重新解释演员阵容: 通过重新解释基础位模式在类型之间转换 但是等等,那是个谎言,因为它只在这些情况下起作用: 当对类型为T1的对象的指针或引用是对不同类型的对象的指针或引用的重新解释(或C样式转换)时,转换总是成功,但是,只有当T1和T2都是标准布局类型且以下情况之一为真时,才能访问生成的指针或引用:T2是对象的(可能是cv限定的)动态类型 T2和T1都是指向同一类型T3 T2是对象动态类型的有符号或无符号变体(可能是cv限定的) T2是一种聚合类型或联合类型,它将上述类型之一作为元素或非静

根据重新解释演员阵容:

通过重新解释基础位模式在类型之间转换

但是等等,那是个谎言,因为它只在这些情况下起作用:

当对类型为
T1
的对象的指针或引用是对不同类型的对象的指针或引用的
重新解释(或C样式转换)时,转换总是成功,但是,只有当
T1
T2
都是标准布局类型且以下情况之一为真时,才能访问生成的指针或引用:
  • T2
    是对象的(可能是cv限定的)动态类型
  • T2
    T1
    都是指向同一类型
    T3
  • T2
    是对象动态类型的有符号或无符号变体(可能是cv限定的)
  • T2
    是一种聚合类型或联合类型,它将上述类型之一作为元素或非静态成员(递归地包括子聚合的元素和包含的联合的非静态数据成员)保存:这样可以安全地从结构的第一个成员和联合的元素强制转换为包含它的结构/联合
  • T2
    是对象动态类型的基类(可能是cv限定的)
  • T2
    char
    unsigned char

根据该清单,一个非法的例子是:

auto foo = 13LL;
auto bar = reinterpret_cast<double&>(foo);
auto-foo=13LL;
自动条=重新解释铸件(foo);
因此,进行转换的唯一可接受的方法是复制内存:

auto foo = 13LL;
double bar;

copy_n(reinterpret_cast<char*>(&foo), sizeof(foo), reinterpret_cast<char*>(&bar));
auto-foo=13LL;
双杠;
复制(重新解释类型(&foo)、大小(foo)、重新解释类型(&bar));

我的问题是,为什么不为我重新解释一下?还是有其他的东西可以让我不必跳过这一圈?

主要是因为对
重新解释演员的限制(没有完全被CPPPreference网站捕获)

  • 对齐问题和
  • 陷阱表示法
对于一个假设的
重新解释\u cast
为数值,可以通过截断或零扩展轻松处理不同的大小,因为一个是进入危险的位级区域,所以这不是问题

通过使用
memcpy
copy\n
可以解决对齐问题,但仍然可能成为陷阱表示的受害者。这意味着结果值的使用可能会失败。在某些平台上,对于某些值


请注意,标准对任何内容的保证都可以并且通常由任何特定的编译器扩展

通常情况下,与仅依靠标准实现的可移植性相比,追求一点点的可移植性是一个好主意

例如,当你不能假定一个字节是8位时,事情很快就会变得复杂。做出这样的假设会降低可移植性。但受支持的平台仍然很大

为什么不为我重新解释一下

一个原因是没有指定大小、对齐方式和位表示,因此这种转换不可移植。然而,这并不能真正证明将行为定义为未定义,而只是定义了实现

通过使其未定义,编译器可以假定不相关类型的表达式不访问同一对象,这可以实现更好的优化。例如,在以下情况下:

int   & i = something();
float & f = something_else();

const int i1 = i;
f = 42;
const int i2 = i;
编译器可以假设
i1
i2
都具有相同的值(
i
通过赋值到
f
而保持不变),并将它们优化为单个常量。违反该假设将导致未定义的行为

或者是有其他的东西可以让我不用跳过这个圈

复制字节是将一个对象类型重新解释为不相关类型的唯一定义良好的方法


reinterpret\u cast
或一个联合体的别名有时可能会起作用(假设大小等匹配),但如果乐观主义者对未定义的行为太聪明,可能会绊倒你。

Ugh,那么你是说即使我的工作也不一定会起作用吗?如中所示,无法确定地进行此强制转换?无法处理不同的大小,因为强制转换的结果是指向别名类型的指针或引用,而该类型对对象的“真实”类型一无所知。它所能做的就是把内存中的任何东西都当作别名类型的对象。@MikeSeymour:在讨论事情时,上下文有点重要。我们正在讨论为什么
reinterpret\u cast
不处理整数和浮点类型值的重新解释。因此,“强制转换的结果是指针或引用”是不正确的(如果支持这种强制转换)。@MikeSeymour:你可能是对的,因为我看到OP使用了强制转换来引用。修正措辞。@JonathanMee:你可以做演员,但取决于最初的片段,你可能会在某个平台上以陷阱表现结束。仅仅被指派就可能造成混乱。不过,在给定的一组平台上(可能相当大),演员阵容是安全的。请注意,使用我们的
重新解释\u cast
,您必须将其转换为指针或引用,然后返回,大小应该更好地匹配。不支持基于值的非指针的
reinterpret\u cast
。此答案仅适用于引用或指针的
reinterpret\u cast
,而不适用于数值。考虑到问题中的复制代码被视为一种解决方案,并且它所做的只是重新解释值位,我认为这个答案根本没有解决具体问题。但是,作为对指针/引用重新解释这一单独问题的回答,这是很好的