在指针中填充-1作为特殊值

fak*_*ken 1 c pointers reserved

在C中,可以在一个东西一个-1的值(例如为0xFFFFFFFF)到一个指针,采用的方法如这一个,并期望这样的存储器地址从不在运行时分配?

这个想法是指针值用作内存地址,除非它具有这个"特殊"-1值.指针应该被认为是内存地址,即使它是NULL(在这种情况下,它指向的对象尚未构建).

我知道这可能与平台有关,但有问题的程序预计会在Linux,Windows和MacOSX中运行.

手头的问题比这里描述的要大得多,因此质疑这种方法的评论或答案都没有用.我知道它有点hacky,但替代方案是一个主要的重构:/

提前致谢.

Cor*_*ica 8

它是GRAS(通常被认为是安全的).没有主要操作系统会分配与您选择的哨兵相冲突的内存.但是,有一些病理情况下做出这种假设是无效的.例如,病态C++编译器可以选择以0xFFFFFFFF启动堆栈,而不违反规范中的任何约束.

在理智的操作系统范围内,几乎不可能将0xFFFFFFFF(或其64位等效值)作为有效的内存地址.它不能是数组的有效内存地址(C++规则禁止它).从技术上讲,它可以是在空间末尾分配的对象的char的有效索引,但是有两件事可以阻止它.

  1. 大多数操作系统都有一些填充
  2. 大多数操作系统使用高内存值作为内核内存.

如果您有机会使用全球价值作为哨兵,那么保证是安全的.

char sentinel;

char* p = "Hello";
char* p2 = 0; // null pointer
char* p3 = &sentinel;

if (p3 == &sentinel)
    cout << "p3 was a sentinel" << endl;
Run Code Online (Sandbox Code Playgroud)


Pas*_*uoq 5

定义没有其他有效地址与之一致的哨兵值的一种方法是静态变量:

static t sentinel;
t *p = &sentinel;
Run Code Online (Sandbox Code Playgroud)

如果您打算假设一个平面地址空间并且所有指针具有相同的宽度,则可以通过声明sentineltypechar而不是 来最小化开销t


回答您的问题(t*)-1

  • -1有类型int. 我建议使用(t*)(uintptr_t)-1,即使对于 64 位平面地址空间,它也更有可能是最后一个地址。

  • 它不是很干净,但它应该适用于所有常见的体系结构,因为只要编译器打算使用无符号比较汇编指令(通常这样做)来比较指针,对于编译器a可能希望放置在地址空间的末尾,&a + 1必须比较大于 &a。实际上,这可以防止最后一个地址被用来存储任何内容。