I'm working on a C project where I use a void*
variable to hold pointer values. I also need to embed some state information within the same variable. For example, I already use NULL
to indicate that the pointer does not refer to any valid memory (i.e., a "null state").
My question is:
Are there any other values—like a specific number (e.g., (void*)-1
)—that are guaranteed to represent an "invalid" or "sentinel" state in a portable way? In other words, besides NULL, are there any standard or recommended values I can store in a void* to indicate that it doesn't point to a valid object?
If not, what is the best practice for embedding extra state information in pointer variables while ensuring portability across different systems?
Any insights or examples would be greatly appreciated.
What did I try?
I attempted to call __builtin_return_address(0)
to retrieve the current function's return address. My idea was to use that address as a unique state marker in a void*
variable—essentially, to represent a specific "state" that is distinct from NULL.
What was I expecting? I expected that since __builtin_return_address(0) returns a concrete address (obtained from the stack during the function call), it could be used as a non-NULL sentinel value. In other words, I thought that because the return address is stored in memory (albeit on the stack), it might serve as a reliable indicator for a special state within the function, separate from a valid pointer or a NULL pointer.
Just use the address of any global.
char ERROR_FOO_OBJ;
#define ERROR_FOO ((void*)&ERROR_FOO_OBJ)
return ERROR_FOO;
if ( p == ERROR_FOO ) ...;
Just-beyond-an-object is a valid pointer (although not one that can be dereferenced). So while unlikely, it's possible to have a valid pointer equal to ERROR_FOO
. If it makes sense to return a pointer that points just beyond an object, you can protect yourself by using the following instead:
char ERROR_CODE_OBJS[2];
#define ERROR_FOO ((void*)&ERROR_CODE_OBJS[1])
return ERROR_FOO;
if ( p == ERROR_FOO ) ...;
Thanks to Nate Eldredge who raised this issue in the comments.