【问题标题】:Bit Shifts on a C Pointer?C指针上的位移?
【发布时间】:2010-12-23 03:29:03
【问题描述】:

我正在进行这个 C 项目,我希望提高内存效率。在某些情况下,我使用我编写的动态数组结构的 void *s 来保存位。我希望使用所有 64(在这种情况下)位。

我很快意识到你实际上不能对指针进行任何位操作。所以我的解决方案如下:

void *p;
((unsigned long)p) << 4;
((unsigned long)p) & 3;

这可以完成工作,但这只是因为在我的计算机上,长整数和指针的大小相等。在所有(或大多数)架构中都会出现这种情况吗?

我真正的问题是:是否有更正确的方法来对指针进行位操作?我曾认为这种方法在 C 中有些常见(将位打包到 void * 中),但是我可能弄错了……

【问题讨论】:

  • 我会使用 uint64_t 代替 stdint.h
  • 如果您的平台的指针少于 64 位,uint64_t 会太大。使用同一标头中的 intptr_t 和 uintptr_t。
  • @sambory - 看起来你需要通过 stdint.h 再靠近一点。
  • 如果您希望将其用作 64 位位域,那么为 32 位平台编译将破坏任何内容,无论您将其转换为什么。正如我在下面的回答中提到的,您想声明指针与您需要的任何大小的位域的联合,因此无论您针对什么平台,该字段的大小都是正确的。
  • 为什么首先需要这样的指针操作?它们唯一合法的用途是用于对齐目的,并且具有不需要从整数转换为整数的变通方法。

标签: c pointers bitwise-operators


【解决方案1】:

如果您的编译器支持它,C99 的 &lt;stdint.h&gt; 标头提供 intptr_tuintptr_t 类型,它们应该足够大以在您的系统上保存一个指针,但它们是整数,因此您可以进行位操作。如果这正是您想要的,那么它真的不能比这更便携了。

【讨论】:

  • 无论如何,您可能不需要完全可移植的解决方案。任何试图将标志存储在指针低位中的位旋转都必然是特定于平台的,因为它依赖于关于对象对齐的假设。因此,无论如何,在移植到新平台时,提问者可能必须做一些工作(或至少是研究)。
  • @Steve - 如果他正在对指针进行一些操作,我当然希望他以后不要取消引用。这听起来就像是便携性的噩梦。如果他这样做,我怀疑他会问他操作的可移植性。
  • 您能解释一下intptr_tuintptr_t 之间的区别吗?
【解决方案2】:

声明指针和位域的联合。

【讨论】:

  • 您仍然需要知道位域的大小,因此您的其他域需要是 intptr_t。我不确定这个或强制转换是否更具可读性。
  • 您将位域设置为满足其他目的所需的大小。然后编译器将确保结构足够大,以便指针和位域中的较大值适合它。这种情况正是工会的目的。
【解决方案3】:

如果您需要对指针进行这种操作,可以将它们强制转换为intptr_tuintptr_t,两者都可以在stdint.h 中找到。这些保证被​​定义为具有足够位来保存指针的特定于平台的整数类型。

那里还有ptrdiff_t,如果你需要一些东西来保持两个指针之间的差异。

【讨论】:

【解决方案4】:

我认为您正在尝试解决错误的问题。真正的问题就在这里:

我正在使用动态的 void *s 我写的数组结构是为了 保持位。

不要使用 void 指针来保存位。使用 void 指针来保存指针。使用无符号整数来保存位。

【讨论】:

  • 我不确定我是否同意重写整个数据结构及其所有相关函数以便能够存储非指针值是否可行。再说一次,也许如果我把我的数据结构写得更正确,我就不会有这个问题了。
  • 好吧,如果你想避免学习数据库的额外工作,你可以使用 Excel 作为数据库,但从长远来看,这会是一个好主意吗?请注意,指针到 int 的转换和返回是完全实现定义的,如果您不小心处理,您可能会以未定义的行为结束。您的结构旨在存储指针。为什么不编写一个专门用于存储位的 BitStore 数据结构,所有的位都在里面,所以你不必在每次调用时都关心它?
  • -1 用于向 OP 讲道。听起来他知道自己想要什么。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-01-25
  • 2016-08-01
  • 1970-01-01
  • 2021-12-19
相关资源
最近更新 更多