연산자 우선순위
연산자 우선순위 개요
연산자 우선순위는 복합 표현식에서 연산자들이 평가되는 순서를 결정합니다.
C++에는 많은 연산자가 있으며, 각각의 우선순위가 정해져 있습니다.
우선순위를 이해하는 것은 복잡한 표현식을 정확히 해석하고 의도한 대로 코드를 작성하는 데 매우 중요합니다.
연산자 우선순위 표
다음은 C++의 주요 연산자들의 우선순위를 높은 것부터 낮은 순으로 나열한 것입니다.
- 범위 해결
::
- 후위 증가/감소
a++
,a--
- 전위 증가/감소
++a
,--a
, 단항+
,-
,!
,~
- 멤버 접근
.
,->
- 곱셈/나눗셈
*
,/
,%
- 덧셈/뺄셈
+
,-
- 비트 시프트
- 관계 연산자
- 등호/불등호
==
,!=
- 비트 AND
&
- 비트 XOR
^
- 비트 OR
|
- 논리 AND
&&
- 논리 OR
||
- 조건 연산자
?:
- 대입 연산자
=
,+=
,-=
,*=
,/=
,%=
,&=
,|=
,^=
,<<=
,>>=
- 순차 실행
,
이 표를 참고하여 복합 표현식의 평가 순서를 예측할 수 있습니다.
결합 규칙
같은 우선순위의 연산자들이 여러 개 있을 때, 결합 규칙이 적용됩니다.
- 왼쪽에서 오른쪽 : 대부분의 이항 연산자
- 오른쪽에서 왼쪽 : 단항 연산자, 조건 연산자, 대입 연산자
#include <iostream>
int main() {
int a = 5, b = 3, c = 2;
int result = a + b - c; // (a + b) - c와 같음
std::cout << "a + b - c = " << result << std::endl;
int result2 = a = b = c; // a = (b = c)와 같음
std::cout << "a = b = c: a = " << a << ", b = " << b << ", c = " << c << std::endl;
return 0;
}
괄호 사용의 중요성
괄호를 사용하면 연산자 우선순위를 명시적으로 지정할 수 있습니다.
이는 코드의 가독성을 높이고 의도를 명확히 표현하는 데 도움이 됩니다.
#include <iostream>
int main() {
int result1 = 5 + 3 * 2; // 11
int result2 = (5 + 3) * 2; // 16
std::cout << "5 + 3 * 2 = " << result1 << std::endl;
std::cout << "(5 + 3) * 2 = " << result2 << std::endl;
return 0;
}
주의해야 할 연산자 조합
증감 연산자와 다른 연산자
증감 연산자를 다른 연산자와 함께 사용할 때는 주의가 필요합니다.
특히 같은 변수에 대해 여러 번의 수정이 일어나는 경우, 미정의 동작(undefined behavior)이 발생할 수 있습니다.
#include <iostream>
int main() {
int i = 5;
int j = ++i + i++; // 미정의 동작
std::cout << "i = " << i << ", j = " << j << std::endl; // 결과가 예측 불가능
return 0;
}
시프트 연산자와 관계 연산자
시프트 연산자는 관계 연산자보다 우선순위가 높습니다. 이로 인해 의도치 않은 결과가 나올 수 있습니다.
#include <iostream>
int main() {
bool result = 1 < 2 << 3; // (1 < 2) << 3이 아니라 1 < (2 << 3)
std::cout << "1 < 2 << 3 is " << std::boolalpha << result << std::endl;
return 0;
}
비트 연산자와 논리 연산자
비트 연산자와 논리 연산자를 혼용할 때는 우선순위에 주의해야 합니다.
#include <iostream>
int main() {
int a = 5, b = 3;
bool result = a & b && a | b; // (a & b) && (a | b)와 같음
std::cout << "a & b && a | b is " << std::boolalpha << result << std::endl;
return 0;
}
연습 문제
- 다음 표현식의 결과를 예측하고, 실제로 프로그램을 작성하여 결과를 확인해보세요.
a)3 + 4 * 2 / (1 - 5)
b)10 * 3 + 7 % 3
c)5 > 3 && 2 < 4 || 6 <= 3
d)15 & 7 | 8 ^ 5
e)1 << 3 + 2
- 다음 표현식을 괄호를 사용하여 명시적으로 표현하세요.
a = b + c * d << 2 & 8
- 다음 코드의 출력을 예측하고, 실제로 프로그램을 작성하여 결과를 확인해보세요.
int x = 5, y = 3, z = 2;
int result = x + y * z > x * y + z ? x : y;
std::cout << result << std::endl;
- 비트 연산자와 논리 연산자를 혼합하여 사용할 때의 주의점을 설명하는 예제를 작성하세요.
- 다음 코드의 출력을 예측하고, 실제로 프로그램을 작성하여 결과를 확인해보세요. 또한, 이 코드의 문제점을 설명하세요.
int i = 5;
printf("%d %d %d\n", i++, i++, ++i);
참고자료
- C++ 표준 문서의 연산자 우선순위 표 : C++ Operator Precedence
- C++ 연산자 결합성 : C++ Operator Associativity
- C++ Core Guidelines의 연산자 관련 규칙 : C++ Core Guidelines
- Effective C++ : 항목 5 "명시적으로 형 변환보다는 컴파일러 경고를 잘 살펴라" - Scott Meyers