Home > Software design >  Safely storing an int-like value in a void* in C on different platforms
Safely storing an int-like value in a void* in C on different platforms

Time:08-15

I have a simple linked list where the primary data is a void*. For one bit of my program I would like to store a list of integer values. I know GList does this using the GINT_TO_POINTER macro:

#define GINT_TO_POINTER(v) ((gpointer)(gssize)(v))

My question is about gssize. This is defined in the .in file and thus I assume takes on a value during config. Unless I'm mistaken, this is the platform's native pointer size. So is it not always going to be size_t?

I wrote code using size_t and it ran OK, but a goal is to run on different platforms, is there a safer way of doing this?

CodePudding user response:

My question is about gssize. This is defined in the .in file and thus I assume takes on a value during config. Unless I'm mistaken, this is the platform's native pointer size. So is it not always going to be size_t?

I presume you mean you think the size of gssize is the same as the platform's native pointer size. It cannot be the size itself (a number) because a type is required in that context.

Even so, that exhibits some misunderstandings. The relative sizes of the types is not the fundamental consideration here, because converting values between pointer and integer types is not necessarily realized as a simple reinterpretation of part or all of the value's bit pattern.

For usefully encoding integer values as pointer values, you need a mechanism and constraints ensuring that you can successfully decode the pointer values back to the original integer values. It is important to understand that standard C does not provide any mechanism certain to achieve that.

The closest it comes is the reverse: stdint.h defines types intptr_t and uintptr_t, with the property that

any valid pointer to void can be converted to this type, then converted back to pointer to void, and the result will compare equal to the original pointer.

(C17 7.20.1.4/1)

Unfortunately, that is not the guarantee you want.

I wrote code using size_t and it ran OK, but a goal is to run on different platforms, is there a safer way of doing this?

Although it is common for size_t to be the same type as uintptr_t, that does not have to be the case, nor do these need to have the same range (which is a different question). Where they differ, uintptr_t would probably be the better choice for your purposes. I anticipate that that will work as desired on many platforms, but again, there is no alternative that standard C guarantees will work portably, everywhere.

  • Related