sizeof(int) == sizeof(void*)?
是否存在与指针大小相同的整数类型? 在所有微架构上都有保证吗?
Is there an integer type with the same size as pointer? Guaranteed on all microarchitectures?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(10)
根据 此维基百科页面,在 C99 中,您的 stdint.h 标头可能声明 intptr_t 和 uintptr_t,但是这当然需要
所以总的来说,我认为这很难。
According to this Wikipedia page, in C99 your stdint.h header might declare intptr_t and uintptr_t, but then that of course requires
So in general I think this one is tough.
简单地说,不。 不保证在所有架构上。
我的问题是:为什么? 如果您想分配一个足够大的类型来存储
void*
,最好的分配方式是(令人惊讶的是:-)一个void*
。 为什么需要将其放入int
中?编辑:根据您对重复问题的评论,您想要存储指针的特殊值 (1,2,3) 以指示额外信息。
不!! 不要这样做!!。 无法保证 1、2 和 3 不是完全有效的指针。 在需要在 4 字节边界上对齐指针的系统中可能会出现这种情况,但是,由于您询问了所有体系结构,我假设您具有较高的可移植性价值。
寻找另一种正确的方法。 例如,使用 union(记忆中的语法,可能是错误的):
然后您可以使用 isPointer 'boolean' 来决定是否应该将 union 视为整数或指针。
编辑:
如果执行速度是最重要的,那么 typedef 解决方案就是最佳选择。 基本上,您必须为要运行的每个平台定义所需的整数。 您可以通过条件编译来做到这一点。 我还会添加运行时检查,以确保您已正确编译每个平台(我在源代码中定义它,但您会将其作为编译器标志传递,例如“
cc -DPTRINT_INT
"):在我的系统(Ubuntu 8.04,32位)上,我得到:
在这种情况下,我知道我需要使用 PTRINT_INT (或 long)进行编译。 可能有一种方法可以在编译时使用 #if 捕获它,但我现在懒得去研究它。 如果您遇到的平台没有足够的整数类型来保存指针,那么您就不走运了。
请记住,使用特殊指针值 (1,2,3) 来表示整数也可能不适用于所有平台 - 这实际上可能是指针的有效内存地址。
不过,如果你不理睬我的建议,我也无能为力阻止你。 毕竟这是你的代码:-)。 一种可能是检查 malloc 的所有返回值,如果得到 1、2 或 3,则再次 malloc(即,有一个 mymalloc() 会自动执行此操作)。 这将是一个轻微的内存泄漏,但它会保证特殊指针和真实指针之间不会发生冲突。
Simply put, no. Not guaranteed on all architectures.
My question is: why? If you want to allocate a type big enough to store a
void*
, the best thing to allocate is (surprisingly enough :-) avoid*
. Why is there a need to fit it within anint
?EDIT: Based on your comments to your duplicate question, you want to store special values of the pointer (1,2,3) to indicate extra information.
NO!! Don't do this!!. There is no guarantee that 1, 2 and 3 aren't perfectly valid pointers. That may be the case in systems where you're required to align pointers on 4-byte boundaries but, since you asked about all architectures, I'm assuming you have portability as a high value.
Find another way to do it that's correct. For example, use the union (syntax from memory, may be wrong):
Then you can use the isPointer 'boolean' to decide if you should treat the union as an integer or pointer.
EDIT:
If execution speed is of prime importance, then the typedef solution is the way to go. Basically, you'll have to define the integer you want for each platform you want to run on. You can do this with conditional compilation. I would also add in a runtime check to ensure you've compiled for each platform correctly thus (I'm defining it in the source but you would pass that as a compiler flag, like "
cc -DPTRINT_INT
"):On my system (Ubuntu 8.04, 32-bit), I get:
In that case, I'd know I needed to compile with PTRINT_INT (or long). There may be a way of catching this at compile time with #if, but I couldn't be bothered researching it at the moment. If you strike a platform where there's no integer type sufficient for holding a pointer, you're out of luck.
Keep in mind that using special pointer values (1,2,3) to represent integers may also not work on all platforms - this may actually be valid memory addresses for pointers.
Still ,if you're going to ignore my advice, there's not much I can do to stop you. It's your code after all :-). One possibility is to check all your return values from malloc and, if you get 1, 2 or 3, just malloc again (i.e., have a mymalloc() which does this automatically). This'll be a minor memory leak but it'll guarantee no clashes between your special pointers and real pointers.
C99 标准定义了标准 int 类型:
C99还定义了size_t和ptrdiff_t:
体系结构的对象最大大小等于整个内存,因此 sizeof(size_t) == sizeof(void*),但我不知道有什么可以移植到 C89 (其中 < code>size_t 是)并保证足够大(其中
uintptr_t
是)。The C99 standard defines standard int types:
C99 also defines size_t and ptrdiff_t:
The architectures I've seen have the maximum size of an object equal to the whole memory, so sizeof(size_t) == sizeof(void*), but I'm not aware of anything that is both portable to C89 ( which
size_t
is ) and guaranteed to be large enough ( whichuintptr_t
is ).这在标准 32 位系统上是正确的,但当然不能保证,并且您可能会发现许多体系结构并非如此。 例如,一个常见的误解是 x86_64 上的 sizeof(int) 将为 8(我猜是因为它是 64 位系统),但事实并非如此。 在 x86_64 上,sizeof(int) 仍然是 4,但 sizeof(void*) 是 8。
This would be true on a standard 32 bit system, but there certainly are no guarantees, and you could find lots of architectures where it isn't true. For example, a common misconception is that sizeof(int) on x86_64 would be 8 (since it's a 64 bit system, I guess), which it isn't. On x86_64, sizeof(int) is still 4, but sizeof(void*) is 8.
这个问题的标准解决方案是编写一个小程序来检查所有 int 类型(short int、int、long int)的大小并将它们与 void* 进行比较。 如果存在匹配,它会发出一段定义 intptr 类型的代码。 您可以将其放入头文件中并使用新类型。
将此代码包含在构建过程中很简单(例如,使用
make
)The standard solution to this problem is to write a small program which checks the sizes of all int types (short int, int, long int) and compares them to void*. If there is a match, it emits a piece of code which defines the intptr type. You can put this in a header file and use the new type.
It's simple to include this code in the build process (using
make
, for example)不,最接近可移植指针的整数类型是
intptr_t
和ptrdiff_t
。No, the closest you will come to a portable pointer-capable integer type would be
intptr_t
andptrdiff_t
.不,
我不相信 C 标准甚至指定了标准 int 大小。 将其与所有架构(8/16/32/64 位等)结合起来,没有办法保证任何事情。
No.
I do not believe the C standard even specifies standard int sizes. Combine that with all the architectures out there (8/16/32/64bit etc) and there is no way to guarantee anything.
int 数据类型将是大多数架构上的答案。
但对于任何(微)架构,都没有没有保证。
int data type would be the answer on most architectures.
But thre is NO guarantee to this for ANY (micro)architecture.
答案似乎是“否”,但如果您需要的只是一种可以同时充当两者的类型,则可以使用联合:
The answer seems to be "no", but if all you need is a type that can act as both, you can use a union:
通常 sizeof(*void) 取决于内存总线宽度(尽管不一定 - RISC AS/400 之前有 48 位地址总线,但有 64 位指针),并且 int 通常与 CPU 的通用寄存器一样大(有也有例外 - SGI C 在 64 位 MIPS 上使用 32 位整数)。
所以没有任何保证。
Usually sizeof(*void) depends on memory bus width (although not necessarily - pre-RISC AS/400 had 48-bit address bus but 64-bit pointers), and int usually is as big as CPU's general-purpose register (there are also exceptions - SGI C used 32-bit ints on 64-bit MIPS).
So there is no guarantee.