I am working on a software implementation of OpenGL, and OpenGL seems to require that I return 32-bit pointers. To save time, I am putting this into a C equivalent of map with 64-bit systems in order to retrieve 64-bit pointers from 32-bit psuedo-addresses. However, on 32-bit systems, this would cause a hassle, and so I should just use the pointer verbatim.
Here is basically what I want to do in my shared header:
#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
Any suggestions on how to do the first if?
As we already know, the size of the pointer in C is dependent only on the word size of a particular system. So, the size of a pointer to a pointer should have the usual values, that is, 2 bytes for a 16-bit machine, 4 bytes for a 32-bit machine, and 8 bytes for a 64-bit machine.
In 64-bit data models, pointer sizes are always 64 bits.
int , long , ptr , and off_t are all 32 bits (4 bytes) in size. int is 32 bits in size. long , ptr , and off_t are all 64 bits (8 bytes) in size.
How to determine pointer size preprocessor C (?)
To determine pointer size in a portable fashion is tricky.
Various pointers sizes
It is not uncommon to have a pointer to a function wider than a pointer to an object or void*
.
Pointers to int
char
, struct
can be of different sizes, although that is rare.
So let us reduce the task to determine void *
pointer size.
Pre-processor math
PP math is limited, so code needs to be careful. Let us stay with integer math.
(u)intptr_t
The optional types (u)intptr_t
, which are very commonly available, are useful here. They allow conversion of a void *
to an integer and then to an equivalent void*
.
Although the integer type size may differ from the pointer type, that, I assert is rare and detectable with _Static_assert
from C11.
Following will handle many C11 platforms. Useful ideas toward a general solution.
#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]
With Is there any way to compute the width of an integer type at compile-time?, code could use, at compile time, the below to find the width of 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)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With