如何确定指针大小预处理器C

zi8p0yeb  于 2023-10-16  发布在  其他
关注(0)|答案(3)|浏览(125)

我正在开发OpenGL的软件实现,OpenGL似乎要求我返回32位指针。为了保存时间,我将其放入一个C语言中,相当于64位系统的map,以便从32位伪地址中检索64位指针。然而,在32位系统上,这会引起麻烦,所以我应该逐字使用指针。
下面是我想在我的共享头中做的基本操作:

#if <64-bit>
    #include <search.h>
    extern void * pointerTable;
    typedef struct {
          int key;
          void* value;
    } intPtrMap;

    inline int compar(const void *l, const void *r) {
        const intPtrMap *lm = l;
        const intPtrMap *lr = r;
        return lm->key - lr->key;
    }

    inline uint32_t allocate(size) {
        void* result = malloc(size);
        intPtrMap *a = malloc(sizeof(intStrMap));
        a->key = (uint32_t) result;
        a->value = result;
        tsearch(a, &pointerTable, compar);
        return (uint32_t) result;
    }

    inline int getPtr(ptr) {
        intPtrMap *find_a = malloc(sizeof(intPtrMap));
        find_a->key = ptr;
        void *r = tfind(find_a, &root, compar);
        return (*(intPtrMap**)r)->value;
    }
#else
    inline uint32_t allocate(size) {
        return (uint32_t) malloc(size);
    }

    inline uint32_t getPtr(ptr) {
        return (uint32_t) ptr;
    }
#endif

有没有什么建议,如何做第一个如果?

ftf50wuq

ftf50wuq1#

如何确定指针大小预处理器C(?)
以可移植的方式确定 * 指针大小 * 是很棘手的。

各种指针大小

指向函数的指针比指向对象或void*的指针更宽的情况并不少见。
指向intcharstruct的指针可以有不同的大小,尽管这种情况很少见。
因此,让我们减少确定void *指针大小的任务。

预处理器数学

PP数学是有限的,所以代码需要小心。让我们继续学习整数数学。

(u)intptr_t

可选类型(u)intptr_t非常常见,在这里很有用。它们允许将void *转换为整数,然后转换为等价的void*
虽然整数类型的大小可能与指针类型不同,但我Assert这是罕见的,可以用C11的_Static_assert检测到。
以下将处理许多C11平台。对一般解决方案有用的想法。

#include <stdint.h>

// C11
_Static_assert(sizeof (void*) == sizeof (uintptr_t), 
    "TBD code needed to determine pointer size");

// C99 or later
#if UINTPTR_MAX == 0xFFFF
  #define PTR16
#elif UINTPTR_MAX == 0xFFFFFFFF
  #define PTR32
#elif UINTPTR_MAX == 0xFFFFFFFFFFFFFFFFu
  #define PTR64
#else
  #error TBD pointer size
#endif

[Edit 2021年]
对于Is there any way to compute the width of an integer type at compile-time?,代码可以在编译时使用下面的来查找uintptr_t的宽度。

/* Number of bits in inttype_MAX, or in any (1<<k)-1 where 0 <= k < 2040 */
#define IMAX_BITS(m) ((m)/((m)%255+1) / 255%255*8 + 7-86/((m)%255+12))
#define UINTPTR_MAX_BITWIDTH IMAX_BITS(UINTPTR_MAX)
00jrzges

00jrzges2#

使用StackOverflow上的其他问题以及Discord上某人的解决方案,我拼凑了这个解决方案:

#if _WIN32 || _WIN64
    #if _WIN64
        #define PTR64
    #else
        #define PTR32
    #endif
#elif __GNUC__
    #if __x86_64__ || __ppc64__
        #define PTR64
    #else
        #define PTR32
    #endif
#elif UINTPTR_MAX > UINT_MAX
    #define PTR64
#else
    #define PTR32
#endif

这应该能够可靠地确定预处理器中的64位或32位指针使用。

k5ifujac

k5ifujac3#

我知道这是一个很老的问题。但我有个新想法。

#define SIZEOF_POINTER (UINTPTR_MAX / 255 % 255)

#if SIZEOF_POINTER == 8
// on 64 bit system
#elif SIZEOF_POINTER == 4
// on 32 bit system
#elif ...
#endif

该代码可以在8/16/32/.../1024位系统上工作。
这个解决方案背后的数学原理非常简单。将UINTPTR_MAX视为基于256的数字。它可以表示为(255,255,255,255...),然后除以255,我们得到(1,1,1,1,...)。
最后一个问题是数一数这个数字中有多少个1。很简单,小数点后有1000000... % 9 = 1,这里肯定是一样的.我们有(1,0,0,0,...)% 255 = 1,(1,0,1,0...)% 255 = 1的个数。这里唯一的限制是1的个数不能超过255。
UINTPTR_MAX(c++11)在此之前,我们总是为此做大量的工作。

相关问题