这是我长期以来的想法。每隔一段时间我就会看到人们使用1或-1作为指针的虚拟值。为了安全地需要一个不同的变量。
可以使用这样的指针吗?我想-1是可以的。但是否也可以使用其他负数?我能确定1不是用过的内存位置吗?如果是这样,我可以使用内存指针。
P.S。我知道在指针中存储其他数据尤其是正值,这是非常非常糟糕的做法。但我只是想知道在任何现实生活中会有什么后果。
答案 0 :(得分:2)
我打赌你的编译器会在你这样做时发出警告吗?这本身应该告诉你它是坏的,应该避免。
许多旧的硬件代码都有针对值的NULL(或nullptr)保护。你在那里放置一个-1,它变成一个无符号的0xffffffff地址(32位的地址)到它的指针,它将快乐地运行你不希望它运行的各种事情。最好的情况是立即访问违规/ seg错误。最糟糕的情况是没有人注意并且事情在2个月之后就会消失,而你被发现是......非常聪明的人,他们非法将非指针值放入指针中并将事情搞砸了。因为这样的错误,乔布斯可能会失败。
顺便说一句,为什么'人'想要在指针中使用1或-1?删除nullptr,NULL或任何语言支持并完成它。否则在那里放一个有效的指针并调用它。
答案 1 :(得分:2)
可移植使用的唯一指针值是指向当前存在的对象和空指针的指针。 (我忽略了函数指针和成员指针。)
空指针的目的是使指针值不指向任何对象,并将不等于任何指向对象的指针进行比较。该语言仅为每种指针类型提供一个这样的指针值。
有时可以方便地拥有多个不同的指针值。
您可以自己定义此类值 - 例如:
const some_type* foo = reinterpret_cast<some_type*>(-1);
const some_type* bar = reinterpret_cast<some_type*>(-2);
严格地说,使用任一值,即使没有解除引用它,也有未定义的行为。 (我知道C的情况就是这样;我认为它对C ++来说也是如此。)但是如果你碰巧知道那些值与任何指向实际对象的指针不同,并且与他们表现得像预期的那样,然后你可以逃脱它。
C标准库中有一些先例。 <signal.h>
为信号处理函数指针定义了三个宏,SIG_DFL
,SIG_ERR
和SIG_IGN
。在一些实现中,这些被定义为转换为适当指针类型的常量-1,0和1。这些定义不具备可移植性 - 但由于它们是实现本身的一部分,因此它们并非必须如此。唯一的要求是它们必须将不等于任何指向用户定义函数的指针进行比较。 (在我使用的实现中,SIG_DFL
恰好是一个空指针;这不是必需的。)
如果库定义了这样的指针,请随意使用它。如果失败,那就是库中的错误。如果您想自己定义这样的指针,请注意,并了解它可能无法在所有实现上正常工作。
另一种方法是定义适当类型的静态对象,并使用指向该对象的指针:
static some_type foo_obj;
static some_type bar_obj;
const some_type* foo = &foo_obj;
const some_type* bar = &bar_obj;
这是可移植的和,它为您提供了保证与空指针和任何指向用户定义对象的指针不相等的指针值。
答案 2 :(得分:1)
这取决于您的编译器和(大多数)操作系统 - 在大多数操作系统上,存在永远无效的地址范围。因此,在这样的操作系统上,可以安全地使用诸如“魔法”之类的地址。指针的值永远不会与任何有效对象相等。只要你从不取消引用它们就应该没问题 - 即使你取消引用它,操作系统也可以定义行为(通常抛出一个特定的信号)。
更便携的替代方案是创建虚拟&#39;全局对象并使用指针作为特殊标记。没有其他有效的对象指针可以比较为虚拟对象指针,并且虚拟对象的额外开销是最小的。