【问题标题】:C compare two pointers greater than if one is nullC比较两个大于如果一个为空的指针
【发布时间】:2016-02-07 09:13:46
【问题描述】:

如果我比较 C 中的两个指针,我知道 C 6.5.8/5 说:

指向稍后声明的结构成员的指针比指向之前在结构中声明的成员的指针要大

这很好,但如果其中一个指针是NULL 怎么办?我知道我可以做到foo != NULL 但例如这是否违反标准:

char *bar = NULL;
char *foo = "foo";
if(foo > bar) { function(); }

在大于的情况下,该部分没有专门针对NULL,这就是我感到困惑的原因。另外,如果您能告诉我它是否适用于 C89 和 C99。

澄清一下,这与只是我引用的标准的一部分的结构无关。该代码与我上面描述的非常相似。我有一些指向数组的指针,其中一个指针可能为空,因此我想知道是否可以使用大于进行比较。

【问题讨论】:

  • 在游览示例中没有任何“指向结构成员的指针”。指向 &s.m 和 s.m 的指针也是不同的东西
  • 您可能会混淆 指针的地址和 指针的内容。这是一个与标准一致的一般性声明,即指向稍后声明的结构的指针将具有更大的地址。当您比较(foo > bar) 时,您是在比较内容
  • 据我所知,这两个变量不是结构成员。
  • 你还不如引用了关于三元组的部分。与 NULL 指针的唯一有效比较是 == NULL!= NULL
  • 如果标准与问题无关,为什么要添加引用?

标签: c pointers c89


【解决方案1】:

您的示例确实未定义。正如 C11, 6.5.8., p5 中所解释的,每条规则都要求指针指向同一个对象 或过去那个物体。

因此,可以使用关系运算符来比较两个指针:<, >, <=, >=,前提是它们指向同一个对象或超过该对象。在所有其他情况下:

6.5.8。关系运算符,

  1. 。在所有其他情况下,行为是未定义的。

值为NULL的指针,一个空指针,不指向一个对象。这在:

6.3.2.3 指针

  1. 如果将空指针常量转换为 指针类型,结果指针,称为空指针,保证比较不相等 指向任何对象或函数的指针。

【讨论】:

  • 最后是一个处理与 NULL 比较的答案,而不是挂在那个“结构成员”上。
  • 所以要明确一点:NULL 只能是 '==' 和 != 比较。任何其他比较 < 等都是未定义的。
  • @bolov 这也让我很困扰,所以我给出了答案。
  • @bolov 是的,仅适用于 NULL ==, !=.
【解决方案2】:

C99 标准说:

如果指向的对象是同一个聚合对象的成员, 指向稍后声明的结构成员的指针比较大于指向成员的指针 在结构的前面声明,并且指向具有较大下标值的数组元素的指针比较大于指向具有较低下标的相同数组元素的指针 价值观。

这里的关键在同一个对象

struct {
  int a; // structrure members
  int b;
} some_struct;

// so pointers to structure members:
&(some_struct.b) > &(some_struct.a)

这同样适用于数组:

char arr[128];
&(arr[100]) > &(arr[1])

如果指针是NULL,那么它很可能不指向同一数据结构的成员,除非您正在对 BIOS 进行编程(即使这样它也违反了标准,因为空指针保证不会指向任何对象内),所以比较变得有点无用

【讨论】:

    【解决方案3】:

    指向稍后声明的结构成员的指针比指向之前在结构中声明的成员的指针要大

    引用仅描述结构内的成员变量。例如:

    struct A {
      int a;
      int b;
    };
    

    那么 A 的任何实例的地址 a 都小于 b。

    换句话说,如果有人写了如下语句:

     A instanceA;
     int* aa = &(instanceA.a);
     int* ab = &(instanceA.b);
    

    那么保证ab>aa作为成员变量b的定义晚于a。

    【讨论】:

      【解决方案4】:

      那段代码在说什么:

      #include <stdio.h>
      
      struct things {
          int blah;
          int laterz;
      };   
      
      struct things t;
      
      int main ( void ) {
      
          int * a = &t.blah;
          int * b = &t.laterz;
      
          printf("%p < %p\n", (void *)a, (void *)b);
          return 0;
      }
      

      指向laterz的指针大于1。

      【讨论】:

        【解决方案5】:

        规范还规定,您只能使用等式或不等式以外的任何其他方式比较两个相关指针。

        因此,如果您有两个指针都指向同一个缓冲区中的不同位置,那么您可以使用大于或小于运算符来比较它们。而不是其他方式。

        例子

        char buffer1[] = "foobar";
        char buffer2[] = "some other text";
        char *ptr1 = buffer1 + 3;
        char *ptr2 = buffer2;
        

        通过以上内容,您可以使用&lt;&gt; 比较buffer1ptr1。您不能使用ptr1ptr2 做到这一点,只能使用==!= 运算符。

        【讨论】:

        • 如何比较 (&lt;, &gt;) 与 NULL
        • @bolov 我真的不确定,但是你必须首先确保其中一个指针实际上 NULL,这使得整个比较有点像毫无意义。
        • @bolov 在实践中,我看不出它会如何失败,除非编译器明确地做了一些禁止它的事情,但是标准似乎不允许它,所以依赖它可能是不明智的.
        • OP 引用的标准的这一部分是关于指向结构字段的指针。你的答案与此无关。
        • @JohnHascall 是的,但是代码或问题的其余部分似乎根本与结构成员无关。另外:“澄清一下,这与我引用的标准的一部分结构无关。”
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-01-20
        • 2019-12-29
        • 2018-02-07
        • 1970-01-01
        相关资源
        最近更新 更多