C언어 증감연산자 파고들기

우연한 계기로 구르미 코딩 테스트를 해보다가 이런 문제를 만났다.




난 당연히 정답이 8, 3, 5일 줄 알았는데 9, 3, 5라고?

왜일까?
이것을 풀기 위해 연산자 우선순위를 생각해봐야 한다.


증감 연산자는 전위연산과 후위연산으로 나뉜다. 전위연산(++a)은 값을 증가시킨 후 증가된 값을 리턴하고, 후위연산(a++)은 현재 값을 리턴한 뒤 나중에 값을 증가시킨다.

그런데 이렇게까지만 생각하고 있으면 문제가 안 풀린다. 뒤에 있는 ++b가 앞에 있는 ++a + b--에 영향을 주는 기이한 현산이 발생하기 때문이다. 또한 앞에 있는 b--도 뒤에 있는 ++b에 영향을 줘서 5가 나온다. 도대체 순서가 어떻게 되는 걸까?

전위 연산자인 ++a는 연산은 그 어떤 연산보다 가장 먼저 실행하되, 그 expression(리턴값)은 확인하는 시점의 a값으로 결정된다. 반대로 후위 연산자는 리턴값 확인 시점 그 당시의 a 값을 expression으로 보낸 뒤 즉시 증감을 수행한다.

위의 문제에서 연산자 우선 순위는 ++a, ++b, +, b--, printf 순이다. 우선 ++a와 ++b가 먼저 진행되면서 a == 3, b == 6이 된다. 이 상태에서 + 연산이 진행되면 그 피연산자인 ++a와 --b의 값을 확인한다. --b는 이 확인 시점에서 6을 리턴하면서 실제값은 다시 5가 된다. +연산의 결과는 9가 되고 이제 printf를 진행한다. printf에서 맨 마지막 ++b 값을 확인할 때는 그 시점의 b값을 리턴하게 되는데 이것은 5이다.


다음 예제를 보자.

int a = 2, b = 5;
int c = --a + b * a++;
printf("%d, %d, %d\n", a, b, c);

정답은 2, 5, 7이다.

우선 전위 연산자인 --a가 수행되어 a == 1 이 된다. 그 다음 곱셈 연산이 수행되는데, 그 순간 곱셈의 피연산자가 되는 b, a++의 값을 확인한다. a++의 값을 확인하면 a는 현재 값인 1을 리턴하고, 동시에 a를 2로 만든다. 곱셈연산의 결과는 5 * 1 => 5가 되고 이제 덧셈 연산을 수행한다. 덧셈 연산의 왼쪽 피연산자 --a의 값을 확인해보면 확인하는 시점의 a 값 2를 리턴한다. 그래서 c는 7이다.


int a = 2, b = 5;
printf("%d, %d, %d, %d\n", b--, b--, b, ++b);


정답은 5, 6, 4, 4 이다. 연산자 순서는 ++, --, --, printf이다. 먼저 ++b가 수행되면서 우선 b == 6이 된다. b-- 가 수행되면 수행당시 값인 6을 리턴하고 5로 만든다. 또 한 번 실행되면 5를 리턴하고 4로 만든다. 마지막으로 printf가 수행될 때 b, ++b의 값을 확인해보면 4이다.

int a = 2, b = 5;
printf("%d, %d, %d, %d\n", b--, b--, b, a + ++b);

여기에서 정답은 5, 6, 4, 8 이다. ++b가 수행되면서 6이 되고 그 다음 우선순위인 덧셈 연산이 수행된다. 이 때 ++b의 값을 확인해보면 6이므로 덧셈 결과는 8이다. 나머지는 위와 같다.


이렇듯 증감연산자는 그 자체로 핵지랄이기 때문에 왠만하면 한 줄에 중복해서 안 쓰는 것이 권장되고, 아니 그냥 안 쓰는 것이 강력히 권장되고, C에 긴밀이 오리엔트된 파이썬에서조차 사라진 이유이기도 하다.



C는 배워도 배워도 끝이 없네 ㅋㅋㅋ

댓글 3개:

Powered by Blogger.