The only pointer values you can portably use are pointers to objects that currently exist and null pointers. (I'm ignoring function pointers and member pointers.)
The purpose of the null pointer is to have a pointer value that doesn't point to any object, and that compares unequal to any pointer that does point to an object. The language only provides one such pointer value for each pointer type.
Sometimes it can be convenient to have more than one distinguished pointer value.
You can define such values yourself -- for example:
const some_type* foo = reinterpret_cast<some_type*>(-1);
const some_type* bar = reinterpret_cast<some_type*>(-2);
Strictly speaking, using either value, even without dereferencing it, has undefined behavior. (I know that's the case for C; I think it's also true for C++.) But if you happen to know that those values are distinct from any pointers that point to actual objects, and that comparisons to them behave as expected, then you can get away with it.
There's some precedent for this in the C standard library. <signal.h>
defines three macros for signal handler function pointers, SIG_DFL
, SIG_ERR
, and SIG_IGN
. In some implementations these are defined as the constants -1, 0, and 1 cast to the appropriate pointer type. Those definitions are not portable -- but since they're part of the implementation itself, they don't have to be. The only requirement is that they must compare unequal to any pointer to a user-defined function. (In the implementation I'm using, SIG_DFL
happens to be a null pointer; that's not required.)
If a library defines such a pointer, feel free to use it. If it fails, it's a bug in the library. If you want to define such a pointer yourself, be careful, and understand that it might not work correctly on all implementations.
An alternative is to define a static object of the appropriate type, and use a pointer to that object:
static some_type foo_obj;
static some_type bar_obj;
const some_type* foo = &foo_obj;
const some_type* bar = &bar_obj;
This is portable and it gives you pointer values that are guaranteed to compare unequal to the null pointer and to any pointers to user-defined objects.