是否存储无效指针自动未定义的行为?

Cha*_*l72 18 c c++ pointers

显然,取消引用无效指针会导致未定义的行为.但是如果只是在指针变量中存储无效的内存地址呢?

请考虑以下代码:

const char* str = "abcdef";
const char* begin = str;
if (begin - 1 < str) { /* ... do something ... */ }
Run Code Online (Sandbox Code Playgroud)

表达式begin - 1求值为无效的内存地址.请注意,我们实际上并没有取消引用此地址 - 我们只是在指针算法中使用它来测试它是否有效.尽管如此,我们仍然需要将无效的内存地址加载到寄存器中.

那么,这是不确定的行为吗?我从来没有想过,因为很多指针算法似乎依赖于这种事情,而指针实际上只是一个整数.但最近我听说即使将无效指针加载到寄存器中的行为也是未定义的行为,因为某些架构会自动抛出总线错误或者其他内容.任何人都可以向我指出C或C++标准的相关部分,无论哪种方式解决这个问题?

Joh*_*itb 14

我在这里有C草案标准,并且由于遗漏而未定义.它定义了ptr + I6.5.6/8的情况

  • 如果指针操作数指向数组对象的元素,并且数组足够大,则结果指向偏离原始元素的元素,使得结果元素和原始数组元素的下标的差异等于整数表达式.
  • 此外,如果表达式P指向数组对象的最后一个元素,则表达式(P)+1指向一个超过数组对象的最后一个元素,如果表达式Q指向一个超过数组对象的最后一个元素,表达式(Q)-1指向数组对象的最后一个元素.

你的案子不适合这些.您的数组也不够大,无法-1调整指针指向不同的数组元素,也不会将任何结果或原始指针指向一个接收端.

  • @Lorehead:术语"优化"的现代用法指的是编译器应该积极地识别将调用UB的情况,并得出结论变量不能保存会导致这种情况出现的值的概念.例如,给定代码`if(p!= 0)doSomething(p); debug_log(*p);`一个"现代"优化编译器可以得出结论,对`doSomething`无条件调用是安全的,因为如果"p"为空,代码将调用UB,即使在目标平台上读取空指针也是如此只会产生毫无意义的价值. (2认同)

jal*_*alf 10

您的代码是未定义的行为,原因不同:

表达begin - 1不能产生一个无效的指针.这是未定义的行为.您不能在超出您正在处理的数组范围内执行指针算术.因此减法本身是无效的,而不是存储结果指针的行为.

  • 只能为进入同一数据对象的两个指针计算ptrdiff_t."在数组范围内"的唯一例外是指针***超出数组的*end*. (2认同)

Pot*_*ter 6

一些架构具有用于保持指针的专用寄存器.将未映射的地址的值放入这样的寄存器中是允许崩溃的.允许整数溢出/下溢崩溃.由于C的目标是在各种平台上工作,因此指针提供了一种安全编程不安全电路的机制.

如果您知道自己不会在具有这种挑剔特性的异国硬件上运行,则无需担心语言未定义的内容.它由平台明确定义.

当然,这个例子是糟糕的风格,没有充分的理由去做.