如何比较指针?

时间:2012-01-31 20:22:47

标签: c++ pointers

假设我有两个指针:

int *a = something;
int *b = something;

如果我想比较它们,看它们是否指向同一个地方(a == b)工作?

8 个答案:

答案 0 :(得分:89)

对于一些事实,这里是规范中的相关文本

等于运算符(==,!=)

可以比较相同类型对象的指针与“直观”预期结果的相等性:

来自C ++ 11标准的§5.10

  

相同类型的指针   (在指针转换之后)可以进行相等性比较。两个相同类型的指针比较等于if   并且只有当它们都为空时,都指向同一个函数,或者两者都代表相同的地址( 3.9.2 )。

     

(省略有关成员指针和空指针常量的比较的详细信息 - 它们继续沿着'Do What We Mean'的同一行继续:)

     
      
  • [...]如果两个操作数均为空,则它们相等。否则,如果只有一个为null,则它们比较不相等。[...]
  •   
     

最“显眼”的警告与虚拟有关,它似乎也是合乎逻辑的预期:

     
      
  • [...]如果其中一个是指向虚拟成员函数的指针,则结果未指定。否则他们   比较等于if和仅当它们引用相同的最派生对象的相同成员时(1.8)   如果用相关类类型的假设对象取消引用,则使用相同的子对象。 [...]
  •   

关系运算符(<,>,< =,> =)

来自C ++ 11标准的§5.9

  

可以比较相同类型的对象或函数(指针转换后)的指针,   结果定义如下:

     
      
  1. 如果同一类型的两个指针p和q指向同一个对象或   函数,或两者都指向同一个数组末尾的一个,或者都是   null,然后p<=qp>=q都生成true,p<qp>q都生成false。
  2.   
  3. 如果同一类型的两个指针p和q指向的不同对象   不是同一个对象的成员或同一个数组的元素或不同的成员   函数,或者只有其中一个为null,p<q, p>q, p<=q,的结果和   p>=q 未指定
  4.   
  5. 如果两个指针指向同一对象的非静态数据成员,或者指向   这些成员的子对象或数组元素,递归地,指向的指针   后来声明的成员比较大,只要两个成员有相同的   访问控制(第11条),并提供他们的班级不是工会。
  6.   
  7. 如果两个指针指向同一对象的非静态数据成员   不同的访问控制(第11条)结果未指定。
  8.   
  9. 如果两个指针指向同一个union对象的非静态数据成员,   他们比较相等(如果需要,转换为void*之后)。如果有两个指针   指向同一个数组的元素或超出数组末尾的元素   指向具有较高下标的对象的指针比较高。
  10.   
  11. 未指定其他指针比较。
  12.   

所以,如果你有:

int arr[3];
int *a = arr;
int *b = a + 1;
assert(a != b); // OK! well defined

也行:

struct X { int x,y; } s;
int *a = &s.x;
int *b = &s.y;
assert(b > a); // OK! well defined

但这取决于你问题中的 something

int g; 
int main()
{
     int h;
     int i;

     int *a = &g;
     int *b = &h; // can't compare a <=> b
     int *c = &i; // can't compare b <=> c, or a <=> c etc.
     // but a==b, b!=c, a!=c etc. are supported just fine
}

奖励:标准库还有什么?

§20.8.5/ 8 :“对于模板greaterlessgreater_equalless_equal,任何指针的特化类型会产生总订单,即使内置运算符<><=>=没有。“

因此,只要您使用void*和朋友,而不是裸std::less<>,您就可以全局订购任何奇怪的operator<

答案 1 :(得分:56)

是的,这就是指针相等的定义:它们都指向同一个位置(或者是pointer aliases

答案 2 :(得分:19)

指针上的==运算符将比较它们的数字地址,从而确定它们是否指向同一个对象。

答案 3 :(得分:13)

总结一下。如果我们想看看两个指针是否指向相同的内存位置,我们可以做到这一点。另外,如果我们想要比较两个指针所指向的内存的内容,我们也可以这样做,只需记住首先取消引用它们。

如果我们有

int *a = something; 
int *b = something;

我们可以使用相同类型的两个指针:

比较内存地址:

a==b

并比较内容:

*a==*b

答案 4 :(得分:1)

用于检查指针别名的简单代码:

int main () {
    int a = 10, b = 20;
    int *p1, *p2, *p3, *p4;

    p1 = &a;
    p2 = &a;
    if(p1 == p2){
        std::cout<<"p1 and p2 alias each other"<<std::endl;
    }
    else{
        std::cout<<"p1 and p2 do not alias each other"<<std::endl;
    }
    //------------------------
    p3 = &a;
    p4 = &b;
    if(p3 == p4){
        std::cout<<"p3 and p4 alias each other"<<std::endl;
    }
    else{
        std::cout<<"p3 and p4 do not alias each other"<<std::endl;
    }
    return 0;
}

输出:

p1 and p2 alias each other
p3 and p4 do not alias each other

答案 5 :(得分:1)

比较指针不是可移植的, 例如在DOS中,不同的指针值指向 到同一位置比较 的指针返回false。

/*--{++:main.c}--------------------------------------------------*/
#include <dos.h>
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
  int   val_a = 123;
  int * ptr_0 = &val_a;
  int * ptr_1 = MK_FP(FP_SEG(&val_a) + 1, FP_OFF(&val_a) - 16);

  printf(" val_a = %d -> @%p\n", val_a, (void *)(&val_a));
  printf("*ptr_0 = %d -> @%p\n", *ptr_0, (void *)ptr_0);
  printf("*ptr_1 = %d -> @%p\n", *ptr_1, (void *)ptr_1);

  /* Check what returns the pointers comparison: */
  printf("&val_a == ptr_0 ====> %d\n", &val_a == ptr_0);
  printf("&val_a == ptr_1 ====> %d\n", &val_a == ptr_1);
  printf(" ptr_0 == ptr_1 ====> %d\n",  ptr_0 == ptr_1);

  printf("val_a = %d\n", val_a);

  printf(">> *ptr_0 += 100;\n");
             *ptr_0 += 100;

  printf("val_a = %d\n", val_a);

  printf(">> *ptr_1 += 500;\n");
             *ptr_1 += 500;

  printf("val_a = %d\n", val_a);

  return EXIT_SUCCESS;
}
/*--{--:main.c}--------------------------------------------------*/

在Borland C 5.0下编译它,结果如下:

/*--{++:result}--------------------------------------------------*/
 val_a = 123 -> @167A:0FFE
*ptr_0 = 123 -> @167A:0FFE
*ptr_1 = 123 -> @167B:0FEE
&val_a == ptr_0 ====> 1
&val_a == ptr_1 ====> 0
 ptr_0 == ptr_1 ====> 0
val_a = 123
>> *ptr_0 += 100;
val_a = 223
>> *ptr_1 += 500;
val_a = 723
/*--{--:result}--------------------------------------------------*/

答案 6 :(得分:1)

这取决于值的类型,以及操作符的定义方式。例如,字符串比较是按值,而不是按地址。但是 char * 通常是按地址(我认为)。

粗心大意的陷阱。没有保证的指针比较运算符,但是

  (void *)a == (void *)b 

可能相当安全。

答案 7 :(得分:-6)

让我们说你必须指点:

int *a = something1;
int *b = something2;

你知道的东西1的地址是&amp; something1。 而且,something2的地址是&amp; something2。

所以你要做的就是检查指针指向的两个地址是否正确。

所以你使用像

这样的东西
if(&something1 == &something2) {
//do something
}

或者您可以使用==运算符来检查指针a是否与指针b具有相等的值。