Skip to content

reinterpret_cast

C++中reinterpret_cast的目的是是实现:alias to an existing object,这在C++\Language-reference\Basic-concept\Data-model\Object\Object.md#Aliase to an existing object 中进行了详细介绍。

pointer、reference的conversion都使用reinterpret_cast

参见:

  • pointer: C-family-language\C-and-C++\Pointer-array-alias\Pointer
  • reference: C++\Language-reference\Reference

cppreference reinterpret_cast conversion

Converts between types by reinterpreting the underlying bit pattern.

NOTE: 上面这段话所描述的就是alias,这在C++\Language-reference\Basic-concept\Data-model\Object\Object.md#Aliase to an existing object 中进行了详细介绍。

Explanation

Only the following conversions can be done with reinterpret_cast, except when such conversions would cast away constness or volatility.

NOTE: 上面这段话的意思是:reinterpret_cast是需要保证CV的,结合下面的例子来进行说明:

#include <iostream>

void func(const void* input)
{
  const int* i = reinterpret_cast<const int*>(input); // 保持CV
  std::cout << *i << std::endl;
}
int main()
{
  const int i = 0;
  func(&i);
}
// g++ test.cpp

函数func的入参是const的,reinterpret_cast的时候,是需要保持CV的,否则会编译报错,如下是错误示例:

#include <iostream>

void func(const void* input)
{
  int* i = reinterpret_cast<int*>(input); // 丢失CV
  std::cout << *i << std::endl;
}
int main()
{
  const int i = 0;
  func(&i);
}

上述程序报错如下:

test.cpp: 在函数‘void func(const void*)’中:
test.cpp:5:39: 错误:从类型‘const void*’到类型‘int*’的 reinterpret_cast 丢失了限定符
  int* i = reinterpret_cast<int*>(input);

上述程序,可以通过const_cast来 drop CV,在“reinterpret_cast VS C-style cast”章节对它进行了详细描述。

Integral type and pointer

NOTE: 关于integral type 和 pointer之间的转换,在C-family-language\C-and-C++\Pointer-array-alias\Pointer-and-integer.md中对此进行了详细的说明。

1)

NOTE: 原文描述的规则没有理解

2) pointer to integral type

A pointer can be converted to any integral type large enough to hold all values of its type (e.g. to std::uintptr_t)

A pointer converted to an integer of sufficient size and back to the same pointer type is guaranteed to have its original value, otherwise the resulting pointer cannot be dereferenced safely (the round-trip conversion in the opposite direction is not guaranteed; the same pointer may have multiple integer representations)

NOTE: 为了保证“sufficient size”,最好使用C99中引入的intptr_tuintptr_t ,关于此,在cmu.edu INT36-C. Converting a pointer to integer or integer to pointer中进行了探讨,在C-and-C++\Pointer-array-alias\Pointer-and-integer.md中收录了这篇文章。

关于intptr_tuintptr_t ,可以参见:

The null pointer constant NULL or integer zero is not guaranteed to yield the null pointer value of the target type; static_cast or implicit conversion should be used for this purpose.

NOTE: 原文中的,这一段话没有理解。

3) integral or enumeration type to pointer

4) std::nullptr_t to integral type

Type aliasing

5) type aliasing through pointer

Examples

Object#Object representation and value representation

#include <cassert>
struct S
{
    char c;  // 1 byte value
             // 3 bytes padding (assuming alignof(float) == 4)
    float f; // 4 bytes value (assuming sizeof(float) == 4)
    bool operator==(const S& arg) const
    { // value-based equality
        return c == arg.c && f == arg.f;
    }
};

void f()
{
    assert(sizeof(S) == 8);
    S s1 = { 'a', 3.14 };
    S s2 = s1;
    reinterpret_cast<unsigned char*>(&s1)[2] = 'b'; // change 2nd byte of padding
    assert(s1 == s2); // value did not change
}
int main()
{
    f();
}
// g++ test.cpp

stackoverflow How to print (using cout) a number in binary form? # A

#include <iostream>
#include <bitset>
#include <climits>

template<typename T>
void show_binrep(const T& a)
{
    const char* beg = reinterpret_cast<const char*>(&a);
    const char* end = beg + sizeof(a);
    while (beg != end)
    {
        std::cout << std::bitset<CHAR_BIT>(*beg++) << ' ';
    }
    std::cout << '\n';
}
int main()
{
    int a, b;
    short c;
    a = 1;
    c = 2;
    b = a << 3;
    show_binrep(a);
    show_binrep(b);
    show_binrep(c);
    float f = 1;
    show_binrep(f);
}
// g++ test.cpp

6) type aliasing through reference

11) OOP type aliasing: type aliasing through pointer

Pointer to function

7) pointer to function conversion

10) OOP pointer to function conversion

reinterpret_cast VS C-style cast

CV

从CV角度来看:

  • reinterpret_cast需要保证CV(关于此,参见cppreference reinterpret_cast conversion#Explanation段,其中给出了示例)
  • C-style cast不需要保证CV

从这个角度来看:C++对C中的type-unsafe做的改善。C++reinterpret_cast保证了type-safe,同时C++提供了const_cast来给予programmer escape from CV的能力,但是相比于C的implicit,C++的const_cast是explicit,因此相比而言,它更加safe。

下面是cppreference reinterpret_cast conversion#Explanation段中给出了示例使用C-style cast重写的结果:

#include <iostream>

void func(const void* input)
{
    int* i = (int*) input;
    std::cout << *i << std::endl;
}
int main()
{
    const int i = 0;
    func(&i);
}
// gcc test.c

上述程序编译通过,但是可能引入undefined behavior,如果在func尝试对input进行修改,则会导致undefined behavior,这体现了了C++ 的type safety。

reinterpret_cast + const_cast 来模拟C-style cast:

#include <iostream>

void func(const void* input)
{
    int* i = const_cast<int*>(reinterpret_cast<const int*>(input)); // 丢失CV
    std::cout << *i << std::endl;
}
int main()
{
    const int i = 0;
    func(&i);
}
// g++ test.cpp

TODO

When to use reinterpret_cast?

Reinterpret_cast vs. C-style cast

using reinterpret_cast to convert char* to vector