【问题标题】:Strange wording in the standard, concerning comparison of pointers标准中关于指针比较的奇怪措辞
【发布时间】:2013-05-14 13:33:02
【问题描述】:

§6.5.8\6(关于 >、=)

如果表达式 P 指向一个数组对象的元素并且 表达式 Q 指向同一个数组对象的最后一个元素, 指针表达式 Q+1 比较大于 P 。在所有其他情况下, 行为未定义。

上面的几个部分,第 6.5.8 节,解释了基本上,指针算术在数组上按预期工作。那就是int a[3]; int *p = a; int *q = &a[2]; //q-p == 3 是有效的。然而,当我读到上面的q > p 是UB。

我错过了什么?

【问题讨论】:

  • 您错过了上一句之前的句子:“指向具有较大下标值的数组元素的指针比指向具有较低下标的同一数组元素的指针要大”。你引用的是一个例外,允许像 [a, a+3) 这样的半开范围。
  • @DyP,哦,好吧。我不得不再读 5 遍才能理解它。另一个愚蠢的问题来自我的身边:(
  • 这是标准,有些人声称这是困难和不直观的表述的标准;)
  • @DyP,哈哈。但是,您应该将此作为答案发布。双关语包容!

标签: c pointers language-lawyer c11


【解决方案1】:

首先,你引用了一段的一部分,第一部分解释了这是引用的内容,我在此处包含该段落:

当比较两个指针时,结果取决于指针中的相对位置 指向的对象的地址空间。如果两个指向对象类型的指针都指向 同一个对象,或者都指向同一个数组对象的最后一个元素,它们 比较相等。如果指向的对象是同一个聚合对象的成员, 指向稍后声明的结构成员的指针比较大于指向成员的指针 在结构的前面声明,以及指向具有较大下标的数组元素的指针 值比较大于指向具有较低下标值的同一数组的元素的指针。所有指向同一个联合对象成员的指针比较相等。如果 表达式 P 指向数组对象的一个​​元素,而表达式 Q 指向同一个数组对象的最后一个元素,指针表达式 Q+1 比较大于 P。在所有其他情况下,行为未定义。

基本上,您所引用的位指的是通常指针必须始终指向独立对象、对象数组的元素或对象数组的结尾。正如你所看到的,通常递增一个已经指向数组最后一个元素的指针会产生一个无效的指针,而且实际上标准中的这个指针绝对不能被取消引用,但是它可以用于一种特殊情况,那就是它可以设置或与另一个指针进行比较。

这在你增加一个指针然后检查它是否超过数组末尾并如果超过则终止的程序中很有用。例如。

int foo = 0;
int ArrSize = 6;
int bar[ArrSize];
while(foo < ArrSize)
{
    foo++;
    printf("%d", bar + 3 < bar + foo);
}

将是合法的,即使在 foo 指向数组末尾之外的最后一种情况下也是如此。

请注意,此示例非常做作,但说明了要点。

如果没有这个规则,这个程序将是未定义的行为。

【讨论】:

  • 最后一次迭代会导致示例代码中出现未定义的行为。 bar + 7 导致 UB 在关于 + 对指针加整数的含义的部分下。
  • @MattMcNabb Argh,你是对的,我使用了错误的运算符,本来打算使用
  • @MattMcNabb 我确实意识到 Q+2 也不例外,我犯的错误,并且总是为此而犯的是数组的长度!= 最后一个元素的索引。我总是从 1 开始而不是从 0 开始计数 :(
猜你喜欢
  • 2021-01-22
  • 2014-07-21
  • 1970-01-01
  • 1970-01-01
  • 2019-06-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多