是否有固定大小的等效于void *?

时间:2014-03-12 13:12:12

标签: c++ pointers c++11

我正在做一些C ++工作,要求我将“普通”(广泛使用)数据类型(例如int)转换为固定大小的对位点,例如std::int32_t。我有一些使用void*的代码,但这会给我带来麻烦。

我知道任何给定指针的大小在给定系统上是相同的 - sizeof(void*) == sizeof(int*) == sizeof(short*) == sizeof(long*)。但我也知道指针的大小可能因系统而异(特别是32位与64位)。为未来的读者编辑:有人指出大小没有保证,指针的绝对或相对。

是否有固定大小的类型能够持有void*?我认为std::intptr_tstd::uintptr_t是潜在的候选人,但我不确定哪个(如果有的话)是正确的。这主要是由于签字;我不确定为什么有intptr_t的签名和无符号形式,因为我的印象不是指针的签名可以控制。 Instinct说我想要使用uintptr_t,因为我不相信指针可以签名,但那时intptr_t是什么?


关于我的需求的更多信息:我正在研究DLL,并且如果可能的话需要保证交叉编译器功能。对于基于整数的类型,这不是太糟糕;我可以将它们转换为幕后的std::intXX_t类型。但我的DLL函数之一做了一些原始内存操作,需要返回void*。我担心这会导致我遇到各种麻烦,如果我不能正确包装它,但我不知道用包裹它:我找不到任何排序保证指针的大小或数据范围。我知道内存本身可以在DLL外部访问;这不是问题。但是确保void*可以安全地从主机EXE到达我的DLL,反之亦然,这是一个更大的问题。

6 个答案:

答案 0 :(得分:5)

intptr_t和uintptr_t不是固定大小的类型,因此它们不足以满足您的声明目的。您特别要求"固定大小的类型能够持有void*。"这不是100%可能的,因为我们不知道将来的系统会有什么样的指针大小(128位可能会在我们的生命周期内发生)。

我建议您使用uint64_t,然后添加static_assert(sizeof(void*) <= sizeof(uint64_t))。有人可能会说,无法保证将void *放入uint64_t即使在断言通过的情况下也能在所有平台上运行,但我认为它对所有实际用途都足够好。

答案 1 :(得分:1)

  

我知道任何给定指针的大小在给定系统上是相同的

不一定。有char*(和void*)大于int*的平台。

  

是否有固定大小的类型能够持有void*

不,因为void*的大小因平台而异。没有大于64位的(标准)固定大小类型,并且不能保证指针不会大于此值。

  

我认为std::intptr_tstd::uintptr_t是潜在的候选人,但我不确定哪一个(如果有的话)是正确的。

它们都被指定为足以容纳任何指针值;但平台的大小可能会有所不同。根据您要对转换后的值进行算术运算(如果有),选择有符号或无符号。

答案 2 :(得分:1)

  

是否有相当于void*的固定大小?

     

但我也知道指针的大小因系统而异(特别是32位与64位)。

总之,上述问题和声明意味着您不仅需要运行流程,而且需要跨流程甚至系统进行移植。您所能做的就是选择一个整体类型,至少与您想要支持的任何系统的最大尺寸一样长。无法保证任何特定尺寸都能永久保持,因此您只需选择您认为合理的尺寸。如果64对您而言足够,请查看您是否有定义uint64_t的标题。

  

我认为std :: intptr_t或std :: uintptr_t是潜在候选人,但我不确定哪一个(如果有的话)是正确的。

这些大小基于正在运行的进程,并且不能保证足够大以容纳来自具有更宽指针大小的其他进程/系统的指针值。

内存地址永远不会消极,因此使用无符号类型是有意义的。可以对从一个存储器地址到另一个存储器地址的偏移进行签名,这就是为什么存在用于存储这种差异的签名类型....

答案 3 :(得分:1)

可以安全地假设即使在不同的编译器中,void*也可以兼容相同的架构。

由于您的目标是DLL,并且您只能将DLL加载到具有相同体系结构的进程中,这应该足以保证互操作性。

答案 4 :(得分:0)

我正在创建一个程序,用于存储(在Java中)C ++中数据结构的本机指针。

由于我希望我的应用程序可移植,因此无论我的系统是否具有32位或64位架构,我都使用Java long(64位整数)来存储指针。

所以,我建议你将指针存储在int64_t变量中。

答案 5 :(得分:0)

如果您只关心内存大小,则可以intptr_tuintptr_t

如果你关心实际值或做一些算术,那么无符号的应该更好。

但两者都不是固定大小,它们的存储大小取决于实现。