使用reinterpret_cast< char *>(p)或static_cast< char *>((void *)p))获得按字节指针差异,哪个更好? [英] reinterpret_cast<char*>(p) or static_cast<char*>((void*)p)) for bytewise pointer difference, which is better?

查看:126
本文介绍了使用reinterpret_cast< char *>(p)或static_cast< char *>((void *)p))获得按字节指针差异,哪个更好?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

以下三种用于提取原始字节指针以用于指针算术的强制转换之间是否有区别? (假设平台上的char是1个字节.)

Is there any difference between the following three casts for extracting raw byte pointers for use in pointer arithmetic? (assume a platform where char is 1 byte.)

  1. static_cast<char*>((void*)ptr))
  2. reinterpret_cast<char*>(ptr)
  3. (已更新)或:static_cast<char*>(static_cast<void*>(ptr))
  1. static_cast<char*>((void*)ptr))
  2. reinterpret_cast<char*>(ptr)
  3. (updated) or: static_cast<char*>(static_cast<void*>(ptr))

我更喜欢哪个?

更多详细信息...

给出一个类中两个成员对象的指针,我想计算一个成员到另一个成员的偏移量,这样我就可以在给定偏移量的情况下重构一个成员的地址,而另一成员的地址就可以重建.

Given pointers to two member objects in a class, I would like to compute an offset from one to the other, so that I can reconstruct the address of one member given an offset and the address of the other member.

// assumed data layout:
struct C {
  // ...
  A a;
  // ...
  B b;
}

我目前使用的代码大致如下:

The code that I use at the moment is along the lines of:

void approach1( A *pa, B *pb )
{
  // compute offset:
  std::ptrdiff_t offset = static_cast<char*>((void*)pa) - static_cast<char*>((void*)pb);
  // then in some other function...
  // given offset and ptr to b, compute ptr to a:
  A *a = static_cast<A*>( (void*)(static_cast<char*>((void*)pb) + offset) );
}

main()
{
  C c;
  approach1(&c.a, &c.b);
}

我想知道以下内容是否更好(或更糟):

I would like to know whether the following is better (or worse):

void approach2( A *pa, B *pb )
{
  std::ptrdiff_t offset = reinterpret_cast<char*>(pa) - reinterpret_cast<char*>(pb);
  // ...
  A *a = reinterpret_cast<A*>( reinterpret_cast<char*>(pb) + offset );
}

这两种方法完全相同吗?它们同样便携吗?

Are the two methods entirely equivalent? Are they equally portable?

我的印象是approach1()更具可移植性,因为" static_cast指向指针往返void*保留地址",而reinterpret_cast<>保证的地址较少(请参见链接的可接受答案).

My impression is that approach1() is more portable, because "static_casting a pointer to and from void* preserves the address," whereas reinterpret_cast<> guarantees less (see accepted answer at link).

我想知道最干净的方法是什么.

I would like to know what the cleanest way to do this is.

更新:目的说明

许多人问到计算这些偏移量的目的是什么.目的是构造实例偏移量的元类表.运行时反射机制将其用于自动GUI的构建和持久性(偏移量未序列化,仅用于遍历结构).该代码已投入生产超过15年.出于这个问题的目的,我只想知道计算指针偏移量的最便捷的方法.我无意对元类系统的工作方式进行重大更改.另外,由于我还有其他用途(例如,共享内存代码的差异指针),因此我通常也对实现此目的的最佳方式感兴趣.

A number of people have asked what is the purpose of computing these offsets. The purpose is to construct a meta-class table of instance offsets. This is used by a runtime reflection mechanism for automatic GUI building and persistance (the offsets are not serialized, just used to traverse the structure). The code has been in production for over 15 years. For the purposes of this question I just want to know the most portable way of computing the pointer offsets. I have no intention of making large changes to the way the metaclass system works. In addition, I'm also generally interested in the best way to do this, as I have other uses in mind (e.g. difference pointers for shared memory code).

注意::我不能使用offsetof(),因为在我的实际代码中,我仅具有指向实例ab的指针,我不一定具有包含类型对象c或其他要使用offsetof()的静态信息.我只能假设ab是同一对象的成员.

NOTE: I can not use offsetof() because in my actual code I only have the pointers to instances a and b, I don't necessarily have the type of the containing object c or other static info to use offsetof(). All I can assume is that a and b are members of the same object.

推荐答案

这两个将导致相同的结果,因此区别主要是语义上的,并且reinterpret_cast完全具有所需操作的含义,以及以下事实:只需一个强制转换而不是两个强制转换(代码中的强制转换越少越好).

These two will lead to the same result so the difference is mostly semantical, and reinterpret_cast has exactly the meaning of the operation you want, plus the fact that only one cast is required instead of two (and the less cast you have in your code the better).

reinterpret_cast

5.2.10/7 :对象指针可以显式转换为其他类型的对象指针.当prvalue v为 将对象指针类型转换为对象指针类型"cv T的指针",结果为static_cast< cv T *>(static_cast< cv void *>(v)).

5.2.10/7: An object pointer can be explicitly converted to an object pointer of a different type. When a prvalue v of object pointer type is converted to the object pointer type "pointer to cv T", the result is static_cast< cv T* >(static_cast< cv void* >(v)).

因此,除非在中年平台上出现了显性随机低水平的不同行为,否则您应该使用:

So except if an exotique random low level different behaviour appears on a middle-age platform, you should definitely go with:

reinterpret_cast<char*>(ptr);

一般.

也就是说,为什么不使用 uintptr_t ?更合适的是,您不需要指针:

That said, why don't you use uintptr_t in your case ? it's even more apropriate, you need no pointer:

void approach3( A *pa, B *pb )
{
  std::ptrdiff_t offset = reinterpret_cast<std::uintptr_t>(pa) - reinterpret_cast<std::uintptr_t>(pb);
  // ...
  A *a = reinterpret_cast<A*>( reinterpret_cast<std::uintptr_t>(pb) + offset );
}

有关其他信息,请参见:

For additional information see:

http://en.cppreference.com/w/cpp/language/reinterpret_cast

这篇关于使用reinterpret_cast&lt; char *&gt;(p)或static_cast&lt; char *&gt;((void *)p))获得按字节指针差异,哪个更好?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆