포인터를 비교하는 방법?


88

2 개의 포인터가 있다고 가정합니다.

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

내가 그들을 비교하고 그들이 같은 장소를 가리키는 지 확인하고 싶다면 (a == b) 작동합니까?


6
IIRC 비교 포인터는 동일한 배열 내의 요소를 가리 키지 않는 한 정의되지 않습니다
sehe

1
@sehe 안녕하세요, 아래 답변은이 오래된 댓글을 취소합니다.
Spencer

답변:


72

예, 이것이 포인터 동등성의 정의입니다. 둘 다 동일한 위치를 가리 킵니다 (또는 포인터 별칭 임).


2
포인터는 기본적으로 컴퓨터의 메모리 주소에 대한 정수 값입니다. 정수를 비교하는 것과 같습니다.
Kemin Zhou

5
@KeminZhou : 이것은 대부분의 최신 컴퓨터에서는 사실이지만 일반적으로 거짓입니다. 심지어 오래된 1980 PC에 8086 AT 그것은 거짓
실레 Starynkevitch

109

여기에 약간의 사실 은 사양의 관련 텍스트입니다.

같음 연산자 (==,! =)

동일한 유형의 객체에 대한 포인터는 '직관적 인'예상 결과와 동일한 지 비교할 수 있습니다.

에서 § 5.10 은 C ++ 11 표준 :

동일한 유형의 포인터 (포인터 변환 후)가 동일한 지 비교할 수 있습니다. 동일한 유형의 두 포인터는 둘 다 null이거나 둘 다 동일한 함수를 가리 키거나 둘 다 동일한 주소 ( 3.9.2 )를 나타내는 경우에만 동일하게 비교됩니다 .

(멤버 및 또는 널 포인터 상수에 대한 포인터 비교에 대한 세부 정보는 제외- '내가 의미하는 바를 수행'의 동일한 행 아래로 계속됩니다.)

  • [...] 두 피연산자가 모두 null이면 동일하게 비교됩니다. 그렇지 않으면 하나만 null이면 같지 않음을 비교합니다. [...]

가장 '눈에 띄는'경고는 가상과 관련이 있으며 예상 할 수있는 논리적 인 것 같습니다.

  • [...] 둘 중 하나가 가상 멤버 함수에 대한 포인터이면 결과는 지정되지 않습니다. 그렇지 않으면, 가장 많이 파생 된 동일한 객체 (1.8)의 동일한 멤버를 참조하는 경우에만 동일하게 비교하거나 연관된 클래스 유형의 가상 객체로 역 참조 된 경우 동일한 하위 객체를 참조하는 경우에만 동일하게 비교합니다. [...]

관계 연산자 (<,>, <=,> =)

에서 § 5.9 은 C ++ 11 표준 :

동일한 유형의 객체 또는 함수에 대한 포인터 (포인터 변환 후)를 다음과 같이 정의 된 결과와 비교할 수 있습니다.

  1. 두 개의 포인터 (P)과 같은 물체 또는 함수 또는 동일한 어레이의 끝을지나 두 지점 중 하나에 동일한 유형 점 Q 또는 그 둘 NULL의 경우 p<=qp>=q모두 참 수율 p<qp>q양 수율 거짓.
  2. 동일한 유형의 두 포인터 p와 q가 동일한 객체의 구성원이 아닌 다른 객체 나 동일한 배열의 요소 또는 다른 함수를 가리 키 거나 둘 중 하나만 null 인 경우 p<q, p>q, p<=q,및 의 결과 p>=q 는 지정되지 않습니다 .
  3. 두 개의 포인터가 동일한 객체의 비 정적 데이터 멤버 나 해당 멤버의 하위 객체 또는 배열 요소를 재귀 적으로 가리키면 나중에 선언 된 멤버에 대한 포인터는 두 멤버가 동일한 액세스 제어를 갖는 경우 더 크게 비교됩니다 (11 절). 그들의 클래스가 노조가 아니라면.
  4. 두 포인터가 액세스 제어가 다른 동일한 객체의 비 정적 데이터 멤버를 가리키는 경우 (Clause 11) 결과는 지정되지 않습니다.
  5. 두 포인터가 동일한 공용체 객체의 비 정적 데이터 멤버를 가리키는 경우 동일하게 비교합니다 ( void*필요한 경우로 변환 한 후 ). 두 포인터가 동일한 배열의 요소를 가리 키거나 배열의 끝을 벗어난 요소를 가리키면 아래 첨자가 더 높은 개체에 대한 포인터가 더 높게 비교됩니다.
  6. 다른 포인터 비교는 지정되지 않습니다.

따라서 다음과 같은 경우 :

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 "템플리트 greater, less, greater_equal, 그리고 less_equal, 어떤 포인터 유형에 대한 전문 내장 사업자 짝수 경우, 전체 순서를 얻을 <, >, <=, >=하지 않습니다."

그래서, 당신은 맨손이 아닌 친구와 사용 하는 한 전 세계적으로 이상한 것을 주문할 수 있습니다 .void*std::less<>operator<


int *a = arr;라인에 stackoverflow.com/questions/8412694/address-of-array에 대한 참조를 포함하면 이점이 있습니까? 나는 아니에요 확인은 관련 충분한 질문에 경우는 ...하지만 질문
nonsensickle

오늘날, 흉내낼 수없는 @JerryCoffin은 표준 라이브러리가에 정의 된 함수 객체 템플릿에 대해 더 엄격한 사양을 가지고 있다는 사실을 알게했습니다 <functional>. 추가되었습니다.
sehe

이 장은 진행중인 C ++ 초안에서 변경된 것 같습니다. 내가 오해하지 않는 한, 더없는 동작은 전혀 없다 : open-std.org/jtc1/sc22/wg21/docs/papers/2014/n4296.pdf
SomeWittyUsername


25

==포인터 의 연산자는 숫자 주소를 비교하여 동일한 객체를 가리키는 지 확인합니다.


12
다중 상속이 관련되면 조금 더 복잡합니다.
fredoverflow

17

요약하자면. 두 포인터가 같은 메모리 위치를 가리키는 지 확인하려면 그렇게 할 수 있습니다. 또한 두 개의 포인터가 가리키는 메모리의 내용을 비교하려면 그렇게 할 수도 있습니다. 먼저 역 참조를 기억하십시오.

우리가 가지고 있다면

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

이것은 우리가 할 수있는 동일한 유형의 두 포인터입니다.

메모리 주소 비교 :

a==b

내용 비교 :

*a==*b

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

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}--------------------------------------------------*/
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.