3 回答
TA贡献1860条经验 获得超9个赞
那是因为指针的行为不像整数。这是未定义的行为,因为标准如此规定。
但是,在大多数平台(如果不是全部)上,如果不取消引用数组,则不会崩溃或出现可疑行为。但是,如果您不取消引用它,那么进行添加有什么意义呢?
就是说,请注意,从技术上讲,在数组末尾加一个表达式是100%“正确的”,并且保证不会按照C ++ 11规范的5.7节§5崩溃。但是,该表达式的结果是不确定的(只保证不会溢出);而任何其他超出数组界限的表达式都是明确的未定义行为。
注意:这并不意味着从一个以上的偏移量进行读写是安全的。您可能将编辑不属于该数组的数据,并会导致状态/内存损坏。您不会导致溢出异常。
我的猜测是这样的,因为不仅取消引用是错误的。还有指针算术,比较指针等。因此,说不做而不是列举可能存在危险的情况,更容易说。
TA贡献1824条经验 获得超6个赞
原始的x86可能与此类语句有关。在16位代码上,指针为16 + 16位。如果将偏移量添加到低16位,则可能需要处理溢出并更改高16位。那是一个缓慢的操作,最好避免。
在这些系统上,array_base+offset
如果offset在范围内(<=数组大小),则保证不会溢出。但是array+5
如果数组仅包含3个元素,则会溢出。
溢出的结果是您得到的指针不在数组的后面,而是在数组的后面。那可能甚至不是RAM,而是内存映射的硬件。如果您构造指向随机硬件组件的指针,C ++标准不会尝试限制发生的事情,即在实际系统上是未定义行为。
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
我敢肯定,这里还有很多其他例子。
- 3 回答
- 0 关注
- 535 浏览
添加回答
举报