reinterpret_cast 转换

来自cppreference.com
< cpp‎ | language
 
 
 
表达式
概述
值类别(左值 lvalue、右值 rvalue、亡值 xvalue)
求值顺序(序列点)
常量表达式
不求值表达式
初等表达式
lambda 表达式(C++11)
字面量
整数字面量
浮点字面量
布尔字面量
字符字面量,包含转义序列
字符串字面量
空指针字面量(C++11)
用户定义字面量(C++11)
运算符
赋值运算符a=ba+=ba-=ba*=ba/=ba%=ba&=ba|=ba^=ba<<=ba>>=b
自增与自减++a--aa++a--
算术运算符+a-aa+ba-ba*ba/ba%b~aa&ba|ba^ba<<ba>>b
逻辑运算符a||ba&&b!a
比较运算符a==ba!=ba<ba>ba<=ba>=b
成员访问运算符a[b]*a&aa->ba.ba->*ba.*b
其他运算符a(...)a,ba?b:c
运算符的替代表示形式
优先级和结合性
折叠表达式(C++17)
new 表达式
delete 表达式
throw 表达式
alignof
sizeof
sizeof...(C++11)
typeid
noexcept(C++11)
运算符重载
类型转换
隐式转换
const_cast
static_cast
reinterpret_cast
dynamic_cast
显式转换 (T)aT(a)
用户定义转换
 

以转译底层位模式在类型间转换。

目录

[编辑] 语法

reinterpret_cast < new_type > ( expression )

返回 new_type 类型的值。

[编辑] 解释

不同于 static_cast ,但类似 const_castreinterpret_cast 表达式不编译成任何 CPU 指令。它纯粹地是指示编译器以如同它有 new_type 类型一般,对待 expression 的位序列(对象表示)的编译器指令。

仅下列转换能用 reinterpret_cast 进行,除了这种转换会转型走常性易变性的情况。

1) 任何整数、枚举、指针或指向成员指针类型表达式能转换到其自身的类型。产生的值与 expression 的相同。(C++11 起)
2) 任何指针能转换成足够大以保有该指针值的任何整数类型(例如转换成 std::uintptr_t
3) 任何整数或枚举类型能转换到指针类型。指针转换到有足够大小的整数再转换回同一指针类型后,保证拥有其原值,否则结果指针无法安全解引用(反向的来回转换不保证;相同指针可拥有多种整数表示)。空指针常量 NULL 或整数不保证生成目标类型的空指针值;为此目的应该用 static_cast隐式转换
4) 任何 std::nullptr_t 类型值,包含 nullptr ,能转换成任何整数类型,如同它是 (void*)0 ,但没有值能转换成 std::nullptr_t ,甚至 nullptr 也不行:为该目的应该用 static_cast(C++11 起)
5) 任何指向 T1 类型对象的指针能转换成指向另一类型 cv T2 对象的指针。这准确地等价于 static_cast<cv T2*>(static_cast<cv void*>(expression)) (这隐含若 T2 的对齐要求不严格于 T1 的,则指针值不改变,且结果指针转换回原类型生成原值)。任何情况下,若类型别名使用规则允许,结果指针才可以安全地解引用(见后述)
6) T1 类型的左值表达式能转换成到 T2 类型的引用。结果是与原左值指代同一对象,但有不同类型的左值或亡值。不创建临时量,不进行复制,不调用构造函数或转换函数。若类型别名使用规则允许,结果引用才能安全访问(见后述)
7) 任何指向函数指针能转换成指向不同函数类型的指针。通过指向相异函数类型的指针调用函数是未定义的,但转换这种指针回指向原函数的指针类型生成指向原函数的指针值。
8) 一些实现上(特别是在任何 POSIX 兼容的系统上,因为被 dlsym 要求),函数指针能转换成 void* 或任何其他对象指针,反之亦然。若实现支持双向的转换,则转换回原类型生成原值,否则结果指针不能安全地解引用或调用。
9) 任何指针类型的空指针值能转换成任何其他指针类型,产生该类型的空指针值。注意空指针常量 nullptr 或任何其他 std::nullptr_t 类型的值不能用 reinterpret_cast 转换成指针:为此目的应该使用隐式转换或 static_cast
10) 指向成员函数的指针右值能转换成指向不同类型的不同成员函数。转换回原类型生成原值,否则结果指针不能安全使用。
11) 指向某类 T1 成员对象的指针右值能转换成指向另一类 T2 的另一成员对象的指针。若 T2 的对齐不严格于 T1 ,则转换到原类型生成原值,否则结果指针不能安全使用。

同所有转型表达式,结果是:

  • 左值,若 new_type 是左值引用或到函数类型的右值引用;
  • 亡值,若 new_type 是到对象类型的右值引用;
  • 否则为纯右值。

[编辑] 关键词

reinterpret_cast

[编辑] 类型别名使用

当到动态类型DynamicType 的指针或引用被 reinterpret_cast (或 C 风格转型)到指向相异类型 AliasedType 的指针或引用时,转型始终成功,仅若下列之一为真,结果指针或引用才可用来访问对象:

  • AliasedType 是(可有 cv 限定的) DynamicType
  • AliasedTypeDynamicType 都是指向同一类型 T 的指针(可能多级,可能在每级有 cv 限定) (C++11 起)
  • AliasedType 是(可有 cv 限定的) 的 DynamicType 的有符号或无符号变体
  • AliasedType聚合类型联合体类型,它保有前述类型之一为元素或非静态成员(递归地包含子聚合体及所含的联合体非静态数据成员):这使得给定指向非静态成员或元素的指针,获得指向结构体或联合体的可用指针是安全的。
  • AliasedTypeDynamicType基类(可有 cv 限定)且 DynamicType 是无非静态数据成员的标准布局类,且 AliasedType 是其首个基类。
  • AliasedTypecharunsigned charstd::byte : 这容许作为字节数组检验任何对象的对象表示

AliasedType 不满足这些要求,则通过新指针或引用访问对象导致未定义行为。这被称为严格别名使用规则,并适用于 C++ 与 C 编程语言。

注意许多 C++ 编译器作为非标准语言扩展放松此规则,以允许通过联合体不活跃成员的错误类型访问(这种访问在 C 中不是未定义)。

同时注意这组规则比 C 编程语言中的等价规则更复杂: C 允许通过指针访问任何兼容类型。 C++ 无兼容类型且不允许通过指针或引用访问布局兼容类型,若它不满足任何列于上的规则(尽管可能允许访问其成员)

[编辑] 注意

C++98 不允许函数指针与 void* 间的转换,这为 DR CWG195 所修正。

[编辑] 示例

演示 reinterpret_cast 的一些用途:

#include <cstdint>
#include <cassert>
#include <iostream>
int f() { return 42; }
int main()
{
    int i = 7;
 
    // 指针到整数并转回
    uintptr_t v1 = reinterpret_cast<uintptr_t>(&i); // static_cast 为错误
    std::cout << "The value of &i is 0x" << std::hex << v1 << '\n';
    int* p1 = reinterpret_cast<int*>(v1);
    assert(p1 == &i);
 
    // 到另一函数指针并转回
    void(*fp1)() = reinterpret_cast<void(*)()>(f);
    // fp1(); 未定义行为
    int(*fp2)() = reinterpret_cast<int(*)()>(fp1);
    std::cout << std::dec << fp2() << '\n'; // 安全
 
    // 通过指针的类型别名使用
    char* p2 = reinterpret_cast<char*>(&i);
    if(p2[0] == '\x7')
        std::cout << "This system is little-endian\n";
    else
        std::cout << "This system is big-endian\n";
 
    // 通过引用的类型别名使用
    reinterpret_cast<unsigned int&>(i) = 42;
    std::cout << i << '\n';
 
    const int &const_iref = i;
    // int &iref = reinterpret_cast<int&>(const_iref); // 编译错误——不能去除 const
    // 必须用 const_cast 代替: int &iref = const_cast<int&>(const_iref);
}

可能的输出:

The value of &i is 0x7fff352c3580
42
This system is little-endian
42

[编辑] 参阅

const_cast 转换 添加或移除 const[编辑]
static_cast 转换 进行基本转换[编辑]
dynamic_cast 转换 进行有检查的多态转换[编辑]
显式转型 在类型间自由转换[编辑]
标准转换 从一个类型到另一类型的隐式转换[编辑]