重新解释为无效是否合法*

问题描述 投票:8回答:3

我在看https://en.cppreference.com/w/cpp/language/reinterpret_cast,我注意到它指定了我们总是可以投射到的合法类型:

  • byte*
  • char*
  • unsigned char*

但我没有在列表中看到void*。这是疏忽吗?我的用例需要一个reinterpret_cast因为我从int**铸造到void*。我最终会从void*回到int**

c++ pointers void-pointers reinterpret-cast double-pointer
3个回答
2
投票

从指针转换为类型到指向包含void的不同类型的指针总是合法的,所以如果T是一个类型,这是合法的C ++:

T* x;
void *y = reinterpret_cast<void *>(x);

在现实世界中它永远不会被使用,因为void *是一个特例,你用static_cast获得相同的值:

void *y = static_cast<void *>(x); // equivalent to previous reinterpret_cast

(事实上​​,上面的转换是隐含的,可以简单地写成void *y = x; - 感谢Michael Kenzel注意到它)

为了更加明确,标准甚至在草案n4659 for C ++ 17中说过8.2.10重新解释cast [expr.reinterpret.cast],§7

当对象指针类型的prvalue v转换为对象指针类型“指向cv T的指针”时,结果为static_cast<cv T*>(static_cast<cv void*>(v))

当您将byte和char称为唯一合法类型时,仅仅针对这些类型取消引用转换后的指针是合法的。 void不包括在这里因为你永远不能解除引用void *


专门回答你的问题

..我正在从int **转换为void *。而且我最终会从void *转变为int **。

该标准保证第一个是标准(读隐式)转换:

类型为“指向cv T的指针”的prvalue,其中T是对象类型,可以转换为类型为“指向cv void的指针”的prvalue。此转换不会改变指针值(6.9.2)。

所以这总是合法的:

int **i = ...;
void *v = i;

对于背铸,标准说(在static_cast段):

类型为“指向cv1 void的指针”的prvalue可以转换为类型为“指向cv2 T的指针”的prvalue,

所以这也是合法的

int **j = static_cast<int **>(v);

和标准确保j == i


5
投票

这些类型不受严格别名规则的约束。这并不意味着它们是唯一可以与reinterpret_cast一起使用的类型。在将对象指针转换为另一个对象指针类型的情况下,如果不满足严格别名规则的要求,则意味着您无法安全地取消引用结果。但是你仍然可以安全地将结果指针强制转换回原始类型,并使用结果as-if它是原始指针。

关于reinterpret_cast的cppreference的相关部分:

(任何对象指针类型T1*都可以转换为另一个对象指针类型cv T2*。这完全等同于static_cast<cv T2*>(static_cast<cv void*>(expression))(这意味着如果T2的对齐要求不比T1更严格,则指针的值不会改变并转换为结果指针返回其原始类型会产生原始值。在任何情况下,如果类型别名规则允许,结果指针只能被安全地解除引用)

当回到原始类型时,AliasedTypeDynamicType是相同的,所以它们是相似的,这是别名规则列出的第一个案例,其中取消引用reinterpret_cast的结果是合法的:

每当尝试通过类型为DynamicType的glvalue读取或修改AliasedType类型的对象的存储值时,除非满足下列条件之一,否则行为是未定义的:

  • AliasedTypeDynamicType是相似的。
  • AliasedTypesigned的(可能是cv合格的)unsignedDynamicType变种。
  • AliasedTypestd::byte,(自C ++ 17以来)charunsigned char:这允许将任何对象的对象表示检查为字节数组。

4
投票

[expr.reinterpret.cast]/7

可以将对象指针显式转换为不同类型的对象指针。

[basic.compound]/3

指向cv void的指针类型或指向对象类型的指针称为对象指针类型。

但是,您不需要使用reinterpret_cast。指向类型为cv-unqualified的每个对象指针类型都可以隐式转换为void*,而逆可以通过static_cast完成。

© www.soinside.com 2019 - 2024. All rights reserved.