是对范围的指针定义明确的比较



给定以下代码:

char buffer[1024];
char * const begin = buffer;
char * const end = buffer + 1024;
char *p = begin + 2000;
if (p < begin || p > end)
    std::cout << "pointer is out of rangen";

进行比较(p < beginp > end)是否定义明确?还是此代码具有未定义的行为,因为指针已超过数组的末端?

如果比较定义很好,那是什么定义?

(额外的信用:begin + 2000的评估本身是否未定义?)

我假设C 11标准。根据第5.7节(添加操作数)第5段,在您进行比较之前,*p = begin + 2000的行为不确定:

如果指针操作数和结果指向 相同的数组对象,或一个过去的数组对象的最后一个元素, 评估不得产生过多的流量;否则,行为 是未固定的。

begin+2000的评估是未定义的,它已超过数组的末端 - 您可以超越一个末端,但不进一步。

来自C 11§5.7/5 加法运算符

当将具有积分类型的表达式添加到指针中时,结果具有指针操作数的类型。如果指针操作数指向数组对象的元素,并且数组足够大,则结果指向与原始元素的元素偏移,以使结果和原始数组元素的下标的差异等于积分表达式。[...]如果指针操作数和结果指向同一数组对象的元素,或一个超过数组对象的最后一个元素,则评估不会产生溢出;否则,行为是 未定义的

要指定指定的指针比较,假设您有有效的指针,那么它们本质上需要成为同一数组(或一个末端的一个)或指向同一访问控制的非静态数据成员的指针同一对象(除非是联合...)。

详细信息在§5.9/2 关系中

可以比较同一类型的对象或功能(在指针转换之后)的指针,结果定义如下:

  • 如果同一类型的两个指针P和Q指向同一对象或功能,或者两个都在一个过去 同一阵列的末端,或均为空数字,然后p&lt; = q and p> = q均可产生true和p&lt; q and p> q 两者都会产生错误。
  • 如果相同类型的两个指针p和q指向不同对象的不同对象 同一数组或不同函数的对象或元素,或者如果其中一个为null,则结果 未指定的p&lt; q,p> q,p&lt; = q,p> = q。
  • 如果两个指针指向同一对象的非静态数据成员,或者指向子对象或数组元素 在此类成员中,递归地,后来声明的成员的指针比较了更大的比较 两个成员具有相同的访问控件(第11条),并提供其班级不是工会。
  • 如果两个指针指向具有不同访问控制的同一对象的非静态数据成员 (第11条)结果未指定。 - 如果两个指针指向同一联合对象的非静态数据成员,则它们将比较平等(之后 如有必要,转换为void*)。如果两个指针指向同一数组的元素或一个元素 数组的末端,具有较高下标的对象的指针比较较高。
  • 其他指针比较未指定。

您的程序的行为不确定,但不是因为比较。

表达式begin + 2000的评估具有不确定的行为,因为结果将指向超过1024个元素阵列末尾的一个以上元素。

引用C 11(实际上是N3485草稿),5.7p4 [expr.add]:

当添加具有积分类型的表达式或减去 从指针中,结果具有指针操作数的类型。[...] 如果指针操作数和结果指向 相同的数组对象,或一个过去的数组对象的最后一个元素, 评估不会产生溢出;否则,行为 是未定义的。

简而言之,仅计算出局外指针具有不确定的行为;之后您在该指针上执行的操作都没关系。

最新更新