(VS C++ 2019) 포인터 Tip.1 포인터와 증감 연산자

2021. 6. 3. 17:19프로그래밍/C

728x90

C언어에는 파이썬에는 없는 포인터가 있습니다.
처음 배울 때는 매우매우 어렵지만, 조금만 익숙해진다면 편리하게 사용할 수 있습니다.
그러나 포인터와 증감연산자를 합쳐놓으면 정말 헷갈리는 표현이 되는데요, 한 번 알아보러 가봅시다.

int i = 10; int* p = &i;

여기 정수형 포인터 p가 있습니다. p는 i의 주소를 가리킵니다. 이때 개발자가 p가 간접참조하는 i값을 v에 대입하면서 p의 주소를 한 칸 옮기려면 어떻게 해야할까요?

int v; v = *p; // *p == i이므로 v = i와 같다. p++;

네, 바로 이렇게 하면 됩니다. v = *p이므로 v에 포인터 p가 간접참조하는 값인 i를 대입하고, p++을 통해 p에 4Byte(int형 포인터이므로)만큼 주소를 옮기면 됩니다.
C는 연산자 우선순위가 있기 때문에 위 식을 한 줄로 나타낼 수 있습니다.

v = *p++;

이렇게 하면 v에 *p를 대입하면서 p의 주소를 한 칸 옮길 수 있습니다.
예를 들어 p가 가리키는 주소를 200이라고 한다면, 후위 증감 연산자는 연산 순서가 제일 빠르기 때문에 p(204) = p(200) + 1의 식에서 p(200)을 먼저 반환하고 p(204)를 나중에 반환하게 됩니다.
따라서 v = *p 가 먼저 실행되고, p++이 실행되는 것이지요.
결과적으로 v에는 10, p에는 204, i = 10이 저장됩니다.

그렇다면 이 코드는 무엇을 의미할까요?

v = (*p)++;

괄호만 추가되고 바뀐건 없네요. 생각해봅시다.
C언어에서 괄호 연산자는 연산을 분리해줍니다. 그래서 앞의 예시와는 결과가 다릅니다. 위 예시는 p가 가리키는 주소를 변화시켰다면, 이 예시는 p가 가리키는 값인 i를 1 증가시키는 것이지요.

순서를 따져보면, 후위 증감 연산자가 먼저 실행이 되겠네요. *p(11) = *p(10) + 1 중에서 *p(10)이 먼저 반환되고 *p(11)이 나중에 반환됩니다.
따라서 v = (*p)가 먼저 실행되고, (*p)++이 실행되는 것이지요.
결과적으로 v에는 10, p에는 200, i = 11이 저장됩니다.

세 번째 예시는 *와 전위 증감 연산자의 조합입니다.

v = *++p;

전위 증감 연산자는 후위 증감 연산자보다 연산자 우선순위가 작습니다. 그래서 *와 ++(전위)의 연산 순서가 같습니다...!
이때는 연산자 결합방향을 알아야 합니다. +와 ++(전위)의 결합방향은 ←(오른쪽에서 왼쪽)입니다. 따라서 이 순서만 지킨다면 헷갈리지 않고 값을 구할 수 있습니다.

오른쪽부터 왼쪽으로 실행된다고 생각하면,
먼저 ++p가 계산되어 p(204) = p(200) + 1 에서 p(204)가 먼저 반환됩니다(전위).
그 다음에 *p가 실행되기 때문에 v 에는 p(204)가 가리키는 값이 대입됩니다. 쓰레기값이지요.
결과적으로 v에는 쓰레기값, p에는 204, i = 10이 저장됩니다.

마지막입니다.

v = ++*p

이 코드도 결합방향만 생각한다면 어렵지 않게 값을 구할 수 있습니다.

오른쪽부터 왼쪽으로 실행된다고 생각하면,
먼저 *p가 실행되어 i값인 10이 반환됩니다.
그 다음에 ++이 실행되기 때문에 11이 v에는 11이 대입됩니다.
결과적으로 v에는 11, p에는 200, i = 11이 저장됩니다.

결과를 정리하면 다음과 같습니다.

1. v = *p++
연산 순서 : ++(후위) > *
의미 : p가 가리키는 값을 v에 대입한 후에 p를 증가한다.
결과 : v = 10, p = 204, i = 10

2. v = (*p)++
연산 순서 : () > ++(후위)
의미 : p가 가리키는 값을 v에 대입한 후에 p가 가리키는 값을 증가한다.
결과 : v = 10, p = 200, i = 11

3. v = *++p
연산 순서 : ++(전위) = *
의미 : p를 증가시킨 후에 p가 가리키는 값을 v에 대입한다.
결과 : v = 쓰레기값, p = 204, i = 10

4. v = ++*p
연산 순서 : ++(전위) = *
의미 : p가 가리키는 값을 가져오고, 그 값을 1증가하여 v에 대입한다.
결과 : v = 11, p = 200, i = 11


다음은 C로 구현한 결과입니다.
포인터 주소가 매번 바뀌기 때문에 포인터 차이로 출력하였습니다.

728x90

'프로그래밍 > C' 카테고리의 다른 글

(VS++ 2019) LNK 2005, LNK 1169 링크 오류 해결법  (0) 2021.05.29