C/C++ 포인터 비교의 기본 원리
두 포인터가 같은 배열을 가리키고 있다면 서로 비교할 수 있습니다. 이때 관계 연산자(<, >, <=, >=)를 사용해 두 포인터의 상대적인 위치를 판단합니다. 반면, 포인터는 메모리 주소를 다루는 특수한 변수이기 때문에 일반 숫자처럼 곱셈이나 나눗셈을 수행할 수는 없습니다.
C 언어에서의 포인터 비교
예제 코드
#include <stdio.h>
int main() {
int *p1;
int *p2;
p1 = (int *)200;
p2 = (int *)300;
if (p1 > p2) {
printf("P1 is greater than p2");
} else {
printf("P2 is greater than p1");
}
return 0;
}실행 결과
P2 is greater than p1
p1은 200, p2는 300이라는 주소값을 가지므로 'p1 > p2' 조건은 거짓이 되어 else 블록이 실행됩니다.
C++에서의 포인터 비교
예제 코드
#include <iostream>
using namespace std;
int main() {
int *p1;
int *p2;
p1 = (int *)200;
p2 = (int *)300;
if (p1 > p2) {
cout << "P1 is greater than p2";
} else {
cout << "P2 is greater than p1";
}
return 0;
}실행 결과
P2 is greater than p1
포인터 비교 시 알아두어야 할 핵심 사항
- 비교 결과가 확정되는 경우: 같은 타입의 두 포인터 p1과 p2가 같은 객체나 함수를 가리키거나, 같은 배열의 마지막 요소 바로 다음 위치(one past the end)를 가리키거나, 둘 다 null 포인터라면 p1<=p2와 p1>=p2는 모두 참(true)이 되고, p1<p2와 p1>p2는 모두 거짓(false)이 됩니다.
- 비교 결과가 정의되지 않는 경우: 같은 타입의 두 포인터가 서로 다른 객체(같은 객체의 멤버나 같은 배열의 요소가 아닌 경우)나 서로 다른 함수를 가리키거나, 둘 중 하나만 null이라면 p1<p2, p1>p2, p1<=p2, p1>=p2의 결과는 정의되지 않습니다(unspecified).
- 멤버 포인터 비교: 두 포인터가 같은 객체의 non-static 데이터 멤버 또는 그 멤버의 하위 객체(subobject)나 배열 요소를 가리키면서 접근 제어(access control) 수준이 동일하다면 비교 결과가 명확하게 정의됩니다.
- 접근 제어가 다른 경우: 두 포인터가 같은 객체의 non-static 데이터 멤버를 가리키더라도 접근 제어 수준이 서로 다르면 비교 결과는 정의되지 않습니다.
참고로 위 예제는 임의의 정수를 주소로 강제 형변환하여 사용한 학습용 코드입니다. 실제 프로그램에서 유효하지 않은 임의의 주소에 접근하면 정의되지 않은 동작(undefined behavior)이 발생할 수 있으므로 주의해야 합니다.