在C中,可以使用诸如this one之类的方法将-1值(例如0xFFFFFFFF)填充到指针中,并期望在运行时永远不会分配这样的内存地址吗?
这个想法是指针值被用作一个内存地址,除非它有这个"特殊的" -1值。指针应该被认为是内存地址,即使它是NULL(在这种情况下,它指向的对象尚未构建)。
据我所知,这可能与平台有关,但有问题的程序预计会在Linux,Windows和MacOSX中运行。
手头的问题比这里描述的要大得多,所以质疑这种方法的评论或答案都没用。我知道它有点hacky,但替代方案是一个主要的重构:/
提前致谢。
答案 0 :(得分:7)
这是GRAS(通常被认为是安全的)。没有主要操作系统会分配与您选择的哨兵相冲突的内存。但是,有一些病理情况下做出这种假设是无效的。例如,病态C ++编译器可以选择以0xFFFFFFFF启动堆栈,而不违反规范中的任何约束。
在理智的操作系统范围内,几乎不可能将0xFFFFFFFF(或其64位等效值)作为有效的内存地址。它不能是数组的有效内存地址(C ++规则禁止它)。从技术上讲,它可以是在空间末尾分配的对象的char的有效索引,但是有两件事可以阻止它。
如果您有机会将全球价值用作哨兵,则可以保证其安全。
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
。实际上,这可以防止最后一个地址用于存储任何内容。