【问题标题】:Type conversion and type casting of pointers in C++C++中指针的类型转换和类型转换
【发布时间】:2020-11-17 22:50:13
【问题描述】:

我一直试图理解类型转换和类型转换之间的区别。我学到的是,本质上,当一种类型的基础值或位表示更改为另一种值时,我们已经执行了转换。在纯类型转换中,我们只是告诉编译器将位模式视为另一种类型。我使用了“纯”,因为强制转换可能会导致转换,在这种情况下,它被称为“显式转换”。

我想了两个例子来说明这种差异。 第一:

float x = 1.5;
float* p1 = &x;
int* p2 = (int*) p1;
int i = *p2;

这里转换指针类型不会对指针值进行任何操作。所以这是纯粹的铸造。在这种情况下,它会导致未定义的行为,因为我们根据 f1.5 的位表示得到 int 值,准确地说是 1069547520。

第二:

B* b = new D();
D* d = static_cast<D*>(b);

其中 D 派生自 B。这里在第一行进行了隐式转换。在第二行也是,强制转换实际上是一种转换。这些是转换,因为指针值可能会改变,必要时调整值以指​​向完整的 D 对象或 B 子对象(我还没有完全理解偏移是如何工作的不过。)

调用用户定义类转换的指针转换是否正确?如果是这样,那么上面的 static_cast 也执行了转换(显式),而我读到的这个答案调用了一个完全不同的概念:

https://stackoverflow.com/a/34268988/1219638-

标准转换是具有内置含义的隐式转换,是与 static_cast 或 C 样式转换等不同的概念。

还有为什么用户定义的类指针的转换称为标准转换?

我可以问最后一个问题吗?我了解到,当类型相关时,C 风格的转换将像 static_cast 一样。这是否意味着 C 风格的转换也会在必要时计算偏移量?

【问题讨论】:

  • 在我的生活中,除了 c 风格的演员表之外,我从来没有使用过任何东西。
  • 第一个例子是UB,见strict aliasing rule
  • 每个问题请回答一个问题。似乎可以归结为“强制转换和转换之间有什么区别”,但问题可能更清楚
  • @IlianZapryanov 类型双关语在 C++ 中是不允许的(在 C 中是这样)
  • 有隐式转换和显式转换。强制转换是显式转换。所有的转换都会创造新的价值,并且永远不会改变任何东西。新值的表示是否与原始值的表示不同是无关紧要的。

标签: c++ pointers casting


【解决方案1】:

重要的是要理解,就 C++ 语言而言,您所说的区别并不存在。所有“*_casts”(及其 C 等效项)都只是(显式)转换。对于该语言,所有转换都会创建一个新对象(如果转换为引用类型,则创建一个对现有对象的新引用)。

指针是对象。 int* p2 = (int*) p1; 执行reinterpret_cast,它创建了一个不同类型的新指针对象p2 是与 p1 不同的对象,即使它们指向相同的内存。如果你做了++p2,那绝不会影响p1 指向的内容。

因此,从语言的角度来看,强制转换只是某些显式转换,它使用其中包含“强制转换”一词的语法(或语法等效与中包含“强制转换”一词的语法)它)。

您试图做出的区分基本上是当转换返回与原始对象相同的二进制值时,以及当它不返回时。好吧,C++ 并不真正关心;所有(非参考)转换都返回一个新对象。当新对象与旧对象二进制相同时,C++ 既没有也不需要术语来描述转换。并且有很多“*_cast”操作可能不会返回二进制相同的值,所以即使想要创建这样一个概念,将其称为“强制转换”也会令人困惑。

还有为什么用户定义的类指针的转换称为标准转换?

因为这是 C++ 标准对它们的称呼。我并不是说我们称它们为“标准”,因为它们符合 C++ 标准。我的意思是 C++ 标准有一个concept called "standard conversion",以及某些类型的指向类are part of that 的指针之间的转换。

“标准转换”是一种可以隐式发生的转换(即:在转换位置没有专门的语法)。指向派生类的指针可以隐式转换为指向可访问基类的指针。这是多态继承的一部分:某些代码可以在派生类实例上进行操作,而无需确切知道它正在操作的类型。多态基类提供编写代码使用的通用接口,派生类提供该接口的各种实现。

【讨论】:

    【解决方案2】:

    我一直试图弄清楚类型转换和类型转换之间的区别。

    这里有区别:

    • 类型转换是一个表达式。它会显式地导致类型转换。
    • 转换包括显式转换和隐式转换。
    • 隐式转换不是由强制转换引起的。它们出现在表达式中......隐含地。

    在这种情况下,它导致了未定义的行为

    正确。

    我们根据 f1.5 的位表示得到 int 值,准确地说是 1069547520。

    请注意,由于行为未定义,我们无法保证获得该精确值。程序的行为可以是任何东西;它可能会崩溃、无法构建、完全按照您的意愿行事,甚至完全按照您不希望的方式行事。

    调用用户定义类转换的指针转换是否正确?

    调用强制转换是很常见的。虽然从技术上讲,强制转换导致转换可能更准确。

    如果是这样,那么上面的 static_cast 也执行了转换(显式)

    正确。

    还有为什么用户定义的类指针的转换称为标准转换?

    因为是指针,指针之间的转换是标准的转换。

    这是否意味着 C 风格的转换也会在必要时计算偏移量?

    是的。如果静态转换必须计算偏移量,而 C 样式转换执行静态转换,则 C 样式转换计算偏移量。

    附:不要使用 C 风格的强制转换。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2013-02-12
      • 1970-01-01
      • 2020-12-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-09-20
      相关资源
      最近更新 更多