C 또는 C++ 코드에서 다음과 같은 문장을 본 적이 있을 것입니다.
c = a+++b;
이 한 줄의 코드는 과연 어떤 의미를 가질까요? 변수 a와 b에 각각 2와 5가 저장되어 있다고 가정해 봅시다. 이 표현식은 두 가지 방식으로 해석될 수 있습니다.
- c = (a++) + b
- c = a + (++b)
증감 연산자에는 후위 증가 연산자(post-increment)와 전위 증가 연산자(pre-increment)가 있으며, 어느 쪽으로 해석되느냐에 따라 결과가 달라집니다.
우선순위와 결합 법칙
여기서 핵심이 되는 개념은 바로 연산자 우선순위(precedence)와 결합 법칙(associativity)입니다. 컴파일러는 토큰을 왼쪽에서 오른쪽으로 읽어 들이며, 가능한 한 가장 긴 토큰을 먼저 만들려는 성질(최대 인출 원칙, maximal munch) 때문에 a++를 하나의 단위로 먼저 묶습니다.
두 가지 해석에 따른 결과는 다음과 같습니다.
- c = (a++) + b → 2 + 5 = 7
- c = a + (++b) → 2 + 6 = 8
그렇다면 실제 컴파일러는 어느 쪽을 선택할까요? 아래 예제 코드로 직접 확인해 보겠습니다.
예제 코드
#include <iostream>
using namespace std;
main() {
int a = 2, b = 5;
int c;
c = a+++b;
cout << "C is : " << c;
}실행 결과
C is : 7
실행 결과가 7로 출력된 것을 보면, 컴파일러는 첫 번째 해석인 c = (a++) + b를 선택했다는 것을 알 수 있습니다. 즉, a의 현재 값인 2를 더한 후에 a가 3으로 증가하는 후위 증가 방식으로 처리된 것입니다.
참고로 이처럼 모호하게 보이는 표현식은 코드 가독성을 크게 떨어뜨리므로, 실제 프로젝트에서는 괄호를 명시적으로 사용하거나 연산을 분리하여 작성하는 것이 좋은 습관입니다.