为了账号安全,请及时绑定邮箱和手机立即绑定

为什么越界指针算术的行为不确定?

为什么越界指针算术的行为不确定?

C++
慕丝7291255 2019-11-20 10:16:45
以下示例来自Wikipedia。int arr[4] = {0, 1, 2, 3};int* p = arr + 5;  // undefined behavior如果我从不取消引用p,那么为什么arr + 5本身是不确定的行为?我希望指针表现为整数-例外,即在取消引用时,指针的值将被视为内存地址。
查看完整描述

3 回答

?
慕码人2483693

TA贡献1860条经验 获得超9个赞

那是因为指针的行为不像整数。这是未定义的行为,因为标准如此规定。

但是,在大多数平台(如果不是全部)上,如果不取消引用数组,则不会崩溃或出现可疑行为。但是,如果您不取消引用它,那么进行添加有什么意义呢?

就是说,请注意,从技术上讲,在数组末尾加一个表达式是100%“正确的”,并且保证不会按照C ++ 11规范的5.7节§5崩溃。但是,该表达式的结果是不确定的(只保证不会溢出);而任何其他超出数组界限的表达式都是明确的未定义行为。

注意:这并不意味着从一个以上的偏移量进行读写是安全的。您可能编辑不属于该数组的数据,并导致状态/内存损坏。您不会导致溢出异常。

我的猜测是这样的,因为不仅取消引用是错误的。还有指针算术,比较指针等。因此,说不做而不是列举可能存在危险的情况,更容易说。


查看完整回答
反对 回复 2019-11-20
?
慕妹3242003

TA贡献1824条经验 获得超6个赞

原始的x86可能与此类语句有关。在16位代码上,指针为16 + 16位。如果将偏移量添加到低16位,则可能需要处理溢出并更改高16位。那是一个缓慢的操作,最好避免。

在这些系统上,array_base+offset如果offset在范围内(<=数组大小),则保证不会溢出。但是array+5如果数组仅包含3个元素,则会溢出。

溢出的结果是您得到的指针不在数组的后面,而是在数组的后面。那可能甚至不是RAM,而是内存映射的硬件。如果您构造指向随机硬件组件的指针,C ++标准不会尝试限制发生的事情,即在实际系统上是未定义行为。


查看完整回答
反对 回复 2019-11-20
?
MMMHUHU

TA贡献1834条经验 获得超8个赞

“未定义的行为”并不意味着它必须在该行代码上崩溃,而是意味着您不能保证任何结果。例如:


int arr[4] = {0, 1, 2, 3};

int* p = arr + 5; // I guess this is allowed to crash, but that would be a rather 

                  // unusual implementation choice on most machines.


*p; //may cause a crash, or it may read data out of some other data structure

assert(arr < p); // this statement may not be true

                 // (arr may be so close to the end of the address space that 

                 //  adding 5 overflowed the address space and wrapped around)

assert(p - arr == 5); //this statement may not be true

                      //the compiler may have assigned p some other value

我敢肯定,这里还有很多其他例子。


查看完整回答
反对 回复 2019-11-20
  • 3 回答
  • 0 关注
  • 535 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信