如果不使用数组外部的数据,访问数据是否不正确?

Is accessing data outside an array incorrect if you don't use it?

本文关键字:数据 访问 不正确 是否 数组 外部 如果不      更新时间:2023-10-16

在我正在编写的算法中,我可以有以下(当然简化了)

int a[3] = {1,2,3};
int b = a[3];
当用于填充b的索引溢出时,I 从不使用b的值,代码是否仍然不正确?我是否必须进行明确的边界检查?

无论您是否使用b,此代码都具有未定义行为。为什么?因为根据定义,a[3]等于*(a+3)。这里引用了标准中的一段话,证明*(a+3)本身是未定义的,无论该值是存储、使用还是保留。

当一个表达式具有类型被加到或减去指针,结果的类型为指针操作数。如果指针操作数指向an的一个元素数组对象,且数组较大够了,结果指向一个元素与原始元素的偏移量的不同之处结果和的下标原始数组元素等于积分表达式。换句话说,如果表达式P指向第i个数组对象的元素表达式(P)+N(等价地,N+(P)和(P)-N(其中N是值n)分别指向的I +n和I - n个元素数组对象,前提是它们存在。此外,如果表达式P点到数组的最后一个元素对象,表达式(P)+1分数组的最后一个元素后面对象,如果表达式Q点数组的最后一个元素之后的一个对象,表达式(Q)-1指向数组对象的最后一个元素。如果指针操作数和结果指向相同的元素数组对象,或倒数一个数组对象的评价不得产生不良后果溢出;否则,行为为定义。

仍然不正确,仍然未定义的行为。做边界检查

int b = *(a + 3); // dereferencing beyond the array bound.

读取a[3]已经导致未定义行为。由于未定义行为从未在本地受到限制,这已经可能导致您的硬盘驱动器被格式化,或者您的计算机出现一个巨大的食肉僵尸。

在现实中,它通常只是工作。但是很容易出现这样的情况,即数组的末尾标志着映射内存区域的结束,因此访问超出该区域的一个元素将导致分段错误。这当然不是堆栈上的int数组的情况,也不是大多数堆实现的情况,但你不应该依赖它。

(获取&a[3]的地址是否也是未定义行为存在很大争议)

这仍然是不正确的,因为您访问了越界内存位置以获取值a[3]并将其存储在变量b中。

您从未使用b的事实可能意味着编译器优化了那行代码,因此您可能从未看到该行存在的任何不利影响。

但是,编译器不需要这样做,代码本身仍然有未定义的行为。

可以。

使用的值,通过复制到b

更具体地说,解引用(a+3)是不允许的,因为表达式(a+3)不是一个有效的指针…表达式 a[3]相当于*(a+3)(其中a已经衰变为指针表达式)。

是的,阅读不存在的a[3]是错误的。

使用b也是错误的,但是已经太晚了。