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

时间:2014-07-08 16:47:17

标签: c pointers reserved

在C中,可以使用诸如this one之类的方法将-1值(例如0xFFFFFFFF)填充到指针中,并期望在运行时永远不会分配这样的内存地址吗?

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

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

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

提前致谢。

2 个答案:

答案 0 :(得分:7)

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

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

  1. 大多数操作系统都有一些填充
  2. 大多数操作系统使用高内存值作为内核内存。
  3. 如果您有机会将全球价值用作哨兵,则可以保证其安全。

    char sentinel;
    
    char* p = "Hello";
    char* p2 = 0; // null pointer
    char* p3 = &sentinel;
    
    if (p3 == &sentinel)
        cout << "p3 was a sentinel" << endl;
    

答案 1 :(得分:3)

定义其他有效地址不会与之匹配的标记值的一种方法是静态变量:

static t sentinel;
t *p = &sentinel;

如果您要假设一个扁平的地址空间并且所有指针都具有相同的宽度,则可以通过声明sentinel类型char而不是t来最小化开销。< / p>


回答有关(t*)-1的问题:

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

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