使用intptr_t而不是void*?

Gep*_*ard 23 c pointers void-pointers intptr 32bit-64bit

使用intptr_t作为通用存储(保存指针和整数值)而不是void*?(如下所示:http://www.crystalspace3d.org/docs/online/manual/Api1_005f0-64_002dBit-Portability-Changes.html)

对于我已经读过的内容:

  • int- > void*- > int往返不保证保持原值; 我猜int- > intptr_t- > int会的
  • 两个指针算术void*intptr_t要求铸件,所以没有在这里得到好处
  • void*表示存储指针时的显式转换次数较少,intptr_t表示存储整数值时转换次数较少
  • intptr_t 需要C99

我还应该考虑什么呢?

Kei*_*son 29

使用intptr_t作为通用存储(保存指针和整数值)而不是void*

没有.

intptr_t不保证存在.首先,正如您所说,它是在C99中引入的.其次,实现不需要具有足够大的整数类型来保持转换的指针值而不丢失信息.

转换intintptr_t和返回不太可能丢失信息,但没有比实际intptr_t更宽的保证int.

如果要存储指针值,请将它们存储在指针对象中.这就是指针对象的用途.

任何指向对象或不完整类型的指针都可以转换void*回来,而不会丢失信息.对指向函数的指针没有这样的保证 - 但任何指向函数的指针都可以转换为任何其他指向函数类型的指针而不会丢失信息.(我指的是C标准;我认为POSIX提供了一些额外的保证.)

如果要在同一对象中存储整数或指针值,首先应该重新考虑您的设计.如果您已经这样做了,并且认为您确实想要这样做,请考虑使用联合(并仔细跟踪您最近存储的值).

有些API使用void*参数来允许传递任意数据; 例如,参见POSIX pthread_create()函数.这可以通过转换整数值来滥用,void*但传递整数对象的地址更安全.

  • 请展开"_unlikely_以丢失信息".`intptr_t`执行往返于一个比较_equally_的指针的往返 - 是你的评论信息丢失可能不是同一位模式. (2认同)
  • @chux:正如我所说,并不能保证`intptr_t`比`int`更宽(尽管我知道没有实现它不是).例如,如果`intptr_t`是32位而`int`是64位,那么将`int`转换为`intptr_t`并返回`int`可能会丢失信息.具体来说,如果`int`值超出`intptr_t`的范围,则第一次转换产生实现定义的结果. (2认同)
  • 抱歉,错误地将答案读作"将_pointer_转换为`intptr_t`并且返回不太可能丢失信息......".我的评论是基于这个想法.同意`int/intptr_t`问题的罕见性. (2认同)

Per*_*rry 5

不,你不能保证任何特定类型是存储指针和整数的合理方式,此外,它会使你的代码混乱.有一个更好的办法.

如果要在同一对象中存储整数和指针,则干净且可移植的方法是使用union:

union foo {
   int integer_foo;
   void *pointer_foo;
}
Run Code Online (Sandbox Code Playgroud)

这是便携式的,允许您以两者中较大者所需的存储大小存储两种物品.保证始终有效.

  • 可以肯定的是,它在联合定义之后缺少一个`;`. (4认同)
  • 就布局而言,int和void *是否具有共同的初始子序列?否则,这不是“可移植的”,不允许您一次存储两个成员,并且绝对不能“总是工作”。 (2认同)
  • @LightnessRacesinOrbit我不认为他声称可以同时存储两个值."both"意味着可以在其中存储"int",并且可以在其中存储"void*",但不存在同时性的建议.NB.如果`int`和`void*`具有共同的初始序列并不重要,因为该规则仅适用于结构. (2认同)