14

是否存在与指针大小相同的整数类型?保证所有微架构?

4

10 回答 10

16

根据此 Wikipedia page,在 C99 中,您的 stdint.h 标头可能会声明 intptr_t 和 uintptr_t,但那当然需要

  • C99
  • 选择实现标准的这个可选部分的编译器实现者

所以总的来说,我认为这个很难。

于 2009-02-02T10:51:20.623 回答
15

简单地说,没有。不保证适用于所有架构。

我的问题是:为什么?如果你想分配一个足够大的类型来存储 a void*,最好的分配是(令人惊讶的是:-) a void*。为什么需要把它放在一个int?

编辑:根据您对重复问题的评论,您希望存储指针 (1,2,3) 的特殊值以指示额外信息。

不!!不要这样做!. 不能保证 1、2 和 3 不是完全有效的指针。在需要在 4 字节边界上对齐指针的系统中可能就是这种情况,但是,由于您询问了所有体系结构,我假设您具有高价值的可移植性。

找到另一种正确的方法。例如,使用联合(内存中的语法,可能是错误的):

typedef struct {
    int isPointer;
    union {
        int intVal;
        void *ptrVal;
    }
} myType;

然后您可以使用 isPointer 'boolean' 来决定是否应该将联合视为整数或指针。

编辑:

如果执行速度是最重要的,那么 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

在这种情况下,我知道我需要使用 PTRIINT_INT(或 long)进行编译。可能有一种方法可以在编译时使用#if 来捕捉它,但我现在懒得研究它。如果您遇到的平台没有足够的整数类型来保存指针,那么您就不走运了。

请记住,使用特殊指针值 (1,2,3) 来表示整数也可能不适用于所有平台 - 这实际上可能是指针的有效内存地址。

不过,如果你要无视我的建议,我也无能为力阻止你。毕竟这是你的代码:-)。一种可能性是检查 malloc 的所有返回值,如果您得到 1、2 或 3,则再次使用 malloc(即,有一个 mymalloc() 自动执行此操作)。这将是一个轻微的内存泄漏,但它可以保证您的特殊指针和真实指针之间没有冲突。

于 2009-02-02T10:59:34.197 回答
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)。

于 2009-02-02T11:00:47.673 回答
4

这在标准的 32 位系统上是正确的,但肯定不能保证,而且您可以找到许多不正确的架构。例如,一个常见的误解是 x86_64 上的 sizeof(int) 将是 8(我猜是因为它是 64 位系统),但事实并非如此。在 x86_64 上,sizeof(int) 仍为 4,但 sizeof(void*) 为 8。

于 2009-02-02T10:51:13.463 回答
2

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)

于 2009-02-02T13:01:44.590 回答
1

不,最接近可移植指针的整数类型将是intptr_tand ptrdiff_t

于 2009-02-02T10:59:03.043 回答
0

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.

于 2009-02-02T11:57:40.193 回答
0

不。

我不相信 C 标准甚至指定标准 int 大小。将其与现有的所有架构(8/16/32/64 位等)结合起来,就无法保证任何事情。

于 2009-02-02T10:52:34.477 回答
0

int 数据类型将是大多数架构的答案。

但是对于任何(微)架构都不能保证这一点。

于 2009-02-02T10:58:21.500 回答
0

答案似乎是“否”,但如果您需要的只是一种可以同时充当两者的类型,则可以使用联合:

union int_ptr_t {
    int i;
    void* p;
};
于 2009-02-02T10:58:41.233 回答