C 프로그래밍에서 하나의 수식에 여러 연산자가 함께 사용될 때, 어떤 연산자가 먼저 계산되는지 아는 것은 매우 중요합니다. 이를 결정하는 기준이 바로 연산자 우선순위(Operator Precedence)와 연산자 결합성(Associativity)입니다. 이 글에서는 두 개념을 예제와 함께 살펴보고, 전체 연산자 우선순위 표까지 한눈에 정리해 드립니다.
연산자 우선순위(Operator Precedence)란?
연산자 우선순위는 하나의 수식(expression) 안에서 어떤 연산자가 먼저 평가될지 그 순서를 결정하는 규칙입니다. C 언어의 모든 연산자에는 고유한 우선순위가 부여되어 있으며, 수식에 두 개 이상의 연산자가 사용되었을 때는 우선순위가 높은 연산자가 먼저 계산되고, 우선순위가 낮은 연산자는 나중에 계산됩니다.
예를 들어 다음 수식을 보겠습니다.
result = 10 + 5 * 2; // 결과: 20곱셈(*)이 덧셈(+)보다 우선순위가 높기 때문에 5 * 2가 먼저 계산된 후 10이 더해져 결과는 20이 됩니다.
연산자 결합성(Associativity)이란?
연산자 결합성은 우선순위가 서로 같은 연산자들이 하나의 수식에 여러 개 있을 때 평가 순서를 결정하는 규칙입니다. C 언어에서 수식에 동일한 우선순위를 가진 연산자가 여러 개 포함되어 있다면, 결합 방향(왼쪽에서 오른쪽 또는 오른쪽에서 왼쪽)에 따라 계산 순서가 정해집니다.
예를 들어 다음 수식을 보겠습니다.
result = 100 / 10 / 5; // 결과: 2나눗셈(/)은 왼쪽에서 오른쪽으로 결합하므로 (100 / 10) / 5 순서로 계산되어 결과는 2가 됩니다.
C 연산자 우선순위 및 결합성 표
아래 표는 C 언어의 주요 연산자들을 우선순위가 높은 순서부터 낮은 순서대로 정리한 것입니다.
| 우선순위 | 연산자 | 연산자 의미 | 결합 방향 |
|---|---|---|---|
| 1 | () [] -> . | 함수 호출 배열 참조 구조체 멤버 접근(포인터) 구조체 멤버 접근 | 왼쪽 → 오른쪽 |
| 2 | ! ~ + - ++ -- & * sizeof(type) | 논리 NOT(부정) 1의 보수 단항 플러스 단항 마이너스 증가 연산자 감소 연산자 주소 연산자 포인터 역참조 변수 크기 반환 및 타입 변환 | 오른쪽 → 왼쪽 |
| 3 | * / % | 곱셈 나눗셈 나머지 | 왼쪽 → 오른쪽 |
| 4 | + - | 덧셈 뺄셈 | 왼쪽 → 오른쪽 |
| 5 | << >> | 왼쪽 시프트 오른쪽 시프트 | 왼쪽 → 오른쪽 |
| 6 | < <= > >= | 작다 작거나 같다 크다 크거나 같다 | 왼쪽 → 오른쪽 |
| 7 | == != | 같다 같지 않다 | 왼쪽 → 오른쪽 |
| 8 | & | 비트 AND | 왼쪽 → 오른쪽 |
| 9 | ^ | 비트 XOR(배타적 OR) | 왼쪽 → 오른쪽 |
| 10 | | | 비트 OR | 왼쪽 → 오른쪽 |
| 11 | && | 논리 AND | 왼쪽 → 오른쪽 |
| 12 | || | 논리 OR | 왼쪽 → 오른쪽 |
| 13 | ?: | 조건(삼항) 연산자 | 오른쪽 → 왼쪽 |
| 14 | = *= /= %= += -= &= ^= |= <<= >>= | 대입 곱셈 후 대입 나눗셈 후 대입 나머지 후 대입 덧셈 후 대입 뺄셈 후 대입 비트 AND 후 대입 비트 XOR 후 대입 비트 OR 후 대입 왼쪽 시프트 후 대입 오른쪽 시프트 후 대입 | 오른쪽 → 왼쪽 |
| 15 | , | 쉼표(구분자) | 왼쪽 → 오른쪽 |
마무리: 괄호를 활용한 명확한 코드 작성
연산자 우선순위와 결합성을 정확히 이해하면 수식이 어떤 순서로 평가되는지 예측할 수 있습니다. 다만 복잡한 수식에서는 우선순위 규칙에만 의존하기보다 괄호()를 사용해 계산 순서를 명확히 지정하는 것이 좋습니다. 이렇게 하면 코드의 가독성이 높아지고, 의도하지 않은 버그를 예방할 수 있습니다.