将 long int* 转换为 long long int*

4

在我的平台上,long int和long long int都是相同的(64位)。我有一个指向long int的指针,想要把它转换为指向long long int的指针。以下是代码:

static_cast<long long int*>(pointer);

不允许使用该方法。在C++11中,正确的方法是什么?

2个回答

6

您需要强制“重新解释”指针:

reinterpret_cast<long long int*>(pointer);

这种转换意味着编译器“停止检查,我知道如何更好地解释该表达式中的二进制数据”。因此,无论何时使用reinterpret_cast时,请仔细检查您对平台、内存对齐等方面的了解。编写一些简单的单元测试,通过valgrind或地址sanitizer运行它们。
所以现在要考虑一下,是否真的需要将这样的指针强制转换。通常,重新设计函数等可以解决此类问题(例如,如果您只需要来自指向值的数据,则将其存储在某个附加变量中等)。您还可以尝试通过编译器强制进行一些检查:
template <typename Dest, typename Src>
Dest* safe_pointer_cast(Src* src)
{
  static_assert(sizeof(Src) == sizeof(Dest), "size of pointed values differ");
  static_assert(alignof(Src) == alignof(Dest), "alignment different");
  return reinterpret_cast<Dest*>(src);
}

2
你可以始终使用 static_assert 来确保它们具有相同的大小。 - Hcorg
1
由于它本质上是不安全的,编程语言迫使程序员变得明确,并让他/她三思而后行 :) - Hcorg
编译器知道是否安全(long int和long long int是相同的),我有一个C库(Intel MKL)需要一个指向long long int的指针,我想在程序中的任何地方都使用相同类型的整数(我使用std::ptrdiff_t,它是我的平台上的long int)。我将使用static_assert来实现它。 - InsideLoop
即使 longlong long 的大小相同,它们也不是相同的类型。你认为的“安全”在大多数情况下都是错误的。因此,你需要明确告诉编译器你知道自己在做什么。 - molbdnilo
1
@InsideLoop:我认为你误解了这里“安全”的含义。编译器可能知道在你的平台上什么是安全的或不安全的,但static_cast在此处不被允许的原因是因为它不能被视为语言上的安全(本质上是多平台的)。因为这种构造可能是非法的,所以语言要求static_cast失败,编译器无法(甚至不应该)对此做任何事情。 - DevSolar
显示剩余5条评论

1

您可以通过额外的存储空间以便携方式完成此操作:

long* ptr = /***/;
long long extra_storage = *ptr;
long long* long_ptr = &extra_storage;

没有额外的存储空间,但有编译时检查:

static_assert(sizeof(long) == sizeof(long long));
long* ptr = /***/;
long long* long_ptr = reinterpret_cast<long long*>(ptr);

在您的第一个示例中,long_ptrextra_storage 变量的 _地址_,而不是它的值。 - DarkDust
@DarkDust 那是真的。 - Maxim Egorushkin

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接