icon안동민 개발노트

연산자 우선순위


연산자 우선순위 개요

 연산자 우선순위는 복합 표현식에서 연산자들이 평가되는 순서를 결정합니다.

 C++에는 많은 연산자가 있으며, 각각의 우선순위가 정해져 있습니다.

 우선순위를 이해하는 것은 복잡한 표현식을 정확히 해석하고 의도한 대로 코드를 작성하는 데 매우 중요합니다.

연산자 우선순위 표

 다음은 C++의 주요 연산자들의 우선순위를 높은 것부터 낮은 순으로 나열한 것입니다.

  1. 범위 해결 ::
  2. 후위 증가/감소 a++, a--
  3. 전위 증가/감소 ++a, --a, 단항 +, -, !, ~
  4. 멤버 접근 ., ->
  5. 곱셈/나눗셈 *, /, %
  6. 덧셈/뺄셈 +, -
  7. 비트 시프트
  8. 관계 연산자
  9. 등호/불등호 ==, !=
  10. 비트 AND &
  11. 비트 XOR ^
  12. 비트 OR |
  13. 논리 AND &&
  14. 논리 OR ||
  15. 조건 연산자 ?:
  16. 대입 연산자 =, +=, -=, *=, /=, %=, &=, |=, ^=, <<=, >>=
  17. 순차 실행 ,

 이 표를 참고하여 복합 표현식의 평가 순서를 예측할 수 있습니다.

결합 규칙

 같은 우선순위의 연산자들이 여러 개 있을 때, 결합 규칙이 적용됩니다.

  • 왼쪽에서 오른쪽 : 대부분의 이항 연산자
  • 오른쪽에서 왼쪽 : 단항 연산자, 조건 연산자, 대입 연산자
예시
#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;
}

연습 문제

  1. 다음 표현식의 결과를 예측하고, 실제로 프로그램을 작성하여 결과를 확인해보세요.

    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

  2. 다음 표현식을 괄호를 사용하여 명시적으로 표현하세요. a = b + c * d << 2 & 8
  3. 다음 코드의 출력을 예측하고, 실제로 프로그램을 작성하여 결과를 확인해보세요.
int x = 5, y = 3, z = 2;
int result = x + y * z > x * y + z ? x : y;
std::cout << result << std::endl;
  1. 비트 연산자와 논리 연산자를 혼합하여 사용할 때의 주의점을 설명하는 예제를 작성하세요.
  2. 다음 코드의 출력을 예측하고, 실제로 프로그램을 작성하여 결과를 확인해보세요. 또한, 이 코드의 문제점을 설명하세요.
int i = 5;
printf("%d %d %d\n", i++, i++, ++i);

 참고자료