是否存在与指针大小相同的整数类型?所有微体系结构都保证了吗?
答案 0 :(得分:16)
根据this Wikipedia page,在C99中你的stdint.h头可能声明intptr_t和uintptr_t,但那当然需要
总的来说,我觉得这个很难。
答案 1 :(得分:14)
简单地说,不。并非所有架构都能保证。
我的问题是:为什么?如果你想分配一个足够大的类型来存储void*
,那么分配的最好的东西(令人惊讶的是:-) a void*
。为什么需要将其纳入int
?
编辑:根据您对重复问题的评论,您希望存储指针(1,2,3)的特殊值以指示额外信息。
NO !!不要这样做!! 。无法保证1,2和3不是完全有效的指针。在您需要在4字节边界上对齐指针的系统中可能就是这种情况,但是,由于您询问了所有体系结构,我假设您将可移植性视为高值。
找到另一种方法,这是正确的。例如,使用union(来自内存的语法,可能是错误的):
typedef struct {
int isPointer;
union {
int intVal;
void *ptrVal;
}
} myType;
然后你可以使用isPointer'boolean'来决定是否应该将union作为整数或指针处理。
编辑:
如果执行速度至关重要,那么typedef解决方案就是最佳选择。基本上,您必须为要运行的每个平台定义所需的整数。您可以使用条件编译来完成此操作。我还会添加运行时检查,以确保您已正确编译每个平台(我在源代码中定义它,但您将其作为编译器标志传递,如“cc -DPTRINT_INT
”):
#include <stdio.h>
#define PTRINT_SHORT
#ifdef PTRINT_SHORT
typedef short ptrint;
#endif
#ifdef PTRINT_INT
typedef int ptrint;
#endif
#ifdef PTRINT_LONG
typedef long ptrint;
#endif
#ifdef PTRINT_LONGLONG
typedef long long ptrint;
#endif
int main(void) {
if (sizeof(ptrint) != sizeof(void*)) {
printf ("ERROR: ptrint doesn't match void* for this platform.\n");
printf (" sizeof(void* ) = %d\n", sizeof(void*));
printf (" sizeof(ptrint ) = %d\n", sizeof(ptrint));
printf (" =================\n");
printf (" sizeof(void* ) = %d\n", sizeof(void*));
printf (" sizeof(short ) = %d\n", sizeof(short));
printf (" sizeof(int ) = %d\n", sizeof(int));
printf (" sizeof(long ) = %d\n", sizeof(long));
printf (" sizeof(long long) = %d\n", sizeof(long long));
return 1;
}
/* rest of your code here */
return 0;
}
在我的系统(Ubuntu 8.04,32位)上,我得到:
ERROR: ptrint typedef doesn't match void* for this platform.
sizeof(void* ) = 4
sizeof(ptrint ) = 2
=================
sizeof(short ) = 2
sizeof(int ) = 4
sizeof(long ) = 4
sizeof(long long) = 8
在这种情况下,我知道我需要使用PTRINT_INT(或long)进行编译。可能有一种方法可以在编译时使用#if来捕获它,但我现在无法对它进行研究。如果你敲击一个没有足以容纳指针的整数类型的平台,那你就不走运了。
请记住,使用特殊指针值(1,2,3)表示整数也可能无法在所有平台上运行 - 这实际上可能是指针的有效内存地址。
但是,如果你不理会我的建议,那么我无能为力阻止你。毕竟这是你的代码:-)。一种可能性是检查malloc中的所有返回值,如果得到1,2或3,则再次选择malloc(即,使用mymalloc()自动执行此操作)。这将是一个小的内存泄漏,但它将保证你的特殊指针和真正的指针之间没有冲突。
答案 2 :(得分:13)
C99标准定义了标准的int类型:
7.18.1.4能够保存对象指针的整数类型 以下类型指定一个带符号的整数类型,其属性是任何有效的void指针都可以转换为此类型,然后转换回指向void的指针,结果将与原始指针进行比较:
intptr_t
以下类型指定一个无符号整数类型,其属性是任何有效的void指针都可以转换为此类型,然后转换回指向void的指针,结果将与原始指针进行比较:
uintptr_t
这些类型是可选的。
C99还定义了size_t和ptrdiff_t:
类型是
ptrdiff_t
是减去两个指针的结果的有符号整数类型;
size_t
这是sizeof运算符的结果的无符号整数类型;和
我见过的体系结构的对象最大大小等于整个内存,所以sizeof(size_t)== sizeof(void *),但我不知道任何可以移植到C89的东西( size_t
是{并且保证足够大(uintptr_t
是)。
答案 3 :(得分:4)
在标准的32位系统上会出现这种情况,但肯定没有保证,你可以找到许多不正确的架构。例如,一个常见的误解是x86_64上的sizeof(int)将是8(因为它是64位系统,我猜),它不是。在x86_64上,sizeof(int)仍为4,但sizeof(void *)为8。
答案 4 :(得分:3)
那么C ++呢?我是否需要完成以下任务:
template <int BITS> struct int_traits_t;
template <> struct int_traits_t <16> {typedef uint16_t int_t;};
template <> struct int_traits_t <32> {typedef uint32_t int_t;};
template <> struct int_traits_t <64> {typedef uint64_t int_t;};
typedef int_traits_t <sizeof (void*) * 8>::int_t myintptr_t;
只是为了得到指针大小的可移植整数?
答案 5 :(得分:2)
这个问题的标准解决方案是编写一个小程序来检查所有int类型(short int,int,long int)的大小,并将它们与void *进行比较。如果匹配,则会发出一段定义intptr类型的代码。您可以将其放在头文件中并使用新类型。
在构建过程中包含此代码很简单(例如,使用make
)
答案 6 :(得分:1)
不,你最接近可移动指针的整数类型将是intptr_t
和ptrdiff_t
。
答案 7 :(得分:0)
没有
我不相信C标准甚至指定standard int sizes。将其与所有架构(8/16/32/64bit等)相结合,无法保证任何内容。
答案 8 :(得分:0)
int数据类型将是大多数架构的答案。
但 ANY (微)架构确保 NO 保证。
答案 9 :(得分:0)
答案似乎是“不”,但如果您需要的是一种既可以作为两者的类型,也可以使用联合:
union int_ptr_t {
int i;
void* p;
};
答案 10 :(得分:0)
通常sizeof(* void)取决于内存总线宽度(尽管不一定 - 前RISC AS / 400有48位地址总线但是64位指针),int通常和CPU的通用寄存器一样大(也有例外 - SGI C在64位MIPS上使用32位整数。)
所以无法保证。