Skip to content

20. 연산자 우선순위


1. 키워드

  • 연산자 우선순위


2. 연산자 우선순위 알아보기

  • C에는 다양한 연산자들끼리 우선순위가 정해져 있다.
  • 연산자 우선순위를 모두 외울 필요는 없으며 필요할 때 찾아보면 된다.
  • 보통 연산자의 계산 순서를 ()(괄호)로 명확하게 나타낸다.


3. 괄호 사용하기

  • 먼저 35 + 1 * 2를 계산해 보자.


#include <stdio.h>

int main()
{
    int num1;

    num1 = 35 + 1 * 2; // 1 * 2가 먼저 계산되므로 35 + 2가 됨

    printf("%d\n", num1); // 37

    return 0;
}


  • 연산자 우선순위에 따라 곱셈이 덧셈보다 우선하므로 1 * 2가 먼저 계산되어 37이 나온다.
  • 기본적으로 계산식은 우선순위가 높은 연산자가 가장 먼저 계산되고, 결합 방향에 따라 순서대로 계산된다.
  • +, *는 결합 방향이 이므로 왼쪽에서 오른쪽 순으로 계산된다.


  • 그럼 35 + 1이 먼저 계산되도록 해보자.


#include <stdio.h>

int main()
{
    int num1;

    num1 = (35 + 1) * 2; // 괄호를 사용하여 35 + 1을 먼저 계산한 뒤 2를 곱함

    printf("%d\n", num1); // 72

    return 0;
}


  • 연산자 우선순위가 낮지만 먼저 계산해야 할 식은 ()로 묶어준다.
  • 즉, (35 + 1) * 235 + 1이 먼저 계산되어 36이 되고 2를 곱하여 72가 나온다.
  • 여기서 ()를 사용한 계산식의 계산 순서는 다음과 같다.


1] ()를 사용한 연산자

2] 우선순위가 높은 연산자

3] 결합방향에 따라 순서대로 계산(+, *는 왼쪽에서 오른쪽)


  • 보통 계산식의 의도를 명확하게 나타내기 위해 우선순위가 높은 연산자라도 ()로 묶어줄 때가 많다.


num1 = 35 + (1 * 2);


  • ()는 여러 번 겹쳐서 사용해도 된다.
  • 계산 결과는 달라지지 않지만 복잡한 식의 가독성을 높이기 위해 주로 사용한다.


num1 = ((35 + 1) * 2);


4. 연산자의 결합 방향 알아보기

  • 보통 연산자는 방향으로 계산을 하지만 방향인 것들도 있다.


#include <stdio.h>

int main()
{
    int num1 = 1;
    int num2;

    num2 = ++num1; // 변수를 먼저 평가하고 앞에 있는 ++을 계산

    printf("%d\n", num2); // 2

    return 0;
}


  • 대표적으로 변수 앞에 붙는 ++= 연산자가 방향이다.
  • ++num1num1 변수를 먼저 평가(계산)하고, 앞에 있는 ++을 계산하여 1을 증가시킨다.
  • num2 = ++num1;에서 할당 연산자 =는 왼쪽에 있는 변수에 값이 들어가므로 방향이다.


  • 만약 다음과 같이 변수 여러 개를 연달아 할당한다면 맨 뒤에 있는 num1 = 10부터 처리되어 num110이 들어간 뒤 방향으로 값이 차례대로 할당된다.


num5 = num4 = num3 = num2 = num1 = 10; // 오른쪽에서 왼쪽으로 차례대로 할당


  • ++, --=뿐만 아니라 +(양의 부호), -(음의 부호), !, ~ 등 변수나 숫자 앞쪽에 붙는 연산자도 방향이다.
  • 단, 변수 뒤에 붙는 ++, --는 연산 방향이 이다.


5. 결합 방향이 다른 연산자와 괄호 사용하기

  • 이번에는 결합 방향이 다른 연산자를 좀 더 많이 사용해 보자.


#include <stdio.h>

int main()
{
    int num1;
    int num2 = 3;

    num1 = 10 + 2 / (5 - 3) * ++num2; // 괄호와 증가 연산자를 먼저 계산

    printf("%d\n", num1); // 14

    return 0;
}


  • 10 + 2 / (5 - 3) * ++num2에서 연산 순서는 다음과 같다.


1] (5 - 3)

2] ++num2

3] 2 / 2

  • 2 / (5 - 3)

4] 1 * 4

  • 2 / (5 - 3) * ++num2

5] 10 + 4

  • 10 + 2 / (5 - 3) * ++num2


  • 먼저 연산자 우선순위에 상관없이 괄호부터 먼저 계산한 뒤 연산자 우선순위 따라 순서대로 계산한다.
  • 그리고 *, /는 결합 방향이 이므로 왼쪽에서 오른쪽 순으로 계산하면 된다.
  • 여기서는 ()로 감싼 (5 - 3)이 먼저 계산된다.
  • 그리고 연산자 우선순위가 가장 높은 ++ 증가 연산자(앞)가 계산된 뒤 *, /이 차례대로 계산된다.
  • 마지막으로 연산자 우선순위가 가장 낮은 +가 계산되어 14가 나오게 된다.


6. 논리, 비교, 시프트 연산자에 괄호 사용하기

  • 산술 연산자와 마찬가지로 논리 연산자도 우선순위가 있고, ()로 묶을 수 있다.


#include <stdio.h>
#include <stdbool.h>

int main()
{
    bool b1;

    b1 = (false || false) && !false || false; // 논리 연산자의 우선순위는 !, &&, || 순

    printf("%d\n", b1); // false AND true 이므로 0

    return 0;
}

// 0


  • 논리 연산자의 우선순위는 !, &&, || 순이다.
  • 따라서 (false || false) && !false || false의 연산 순서는 다음과 같다.


1] (false || false)

2] !false

3] false && true

  • (false || false) && !false

4] false || false

  • (false || false) && !false || false


  • AND 연산자와 OR 연산자 중 어떤 것을 먼저 계산하더라도 OR 연산자의 특성 때문에 결과는 언제나 같지만 우선순위 규칙으로는 OR 연산자보다 AND 연산자가 높다.


  • 비교 연산자를 사용할 때도 우선순위를 잘 따져야 한다.


#include <stdio.h>

int main()
{
    int num1;

    num1 = 5 == 5 < 10; // ==보다 <의 우선순위가 높음

    printf("%d\n", num1); // 0

    return 0;
}


  • 비교 연사자 중 ==보다 <의 우선순위가 높다.
  • 따라서 5 < 10이 먼저 계산되어 1이 나오고, 15가 같은지 비교한다.
  • 15는 다르므로 최종 결과는 0이 나온다.


  • 시프트 연산자와 산술 연산자를 섞어서 사용할 때도 연산자 우선순위에 주의한다.


#include <stdio.h>

int main()
{
    int num1 = 1;
    int num2 = 2;
    int num3;

    num3 = num1 << 2 + num2 << 1; // <<보다 +의 우선순위가 높음

    printf("%d\n", num3); // 32

    return 0;
}


  • 시프트 연산자와 산술 연산자 중 산술 연산자의 우선순위가 더 높다.
  • 즉, <<보다 +가 먼저 계산된다.
  • 따라서 2 + num2가 먼저 계산되어 결국에는 num1 << 4 << 1의 형태가 된다.


  • 보통 num1 << 2 + num2 << 1;과 같은 코드는 시험에서나 볼 뿐 실무에서는 다음과 같이 ()로 계산 의도를 명확하게 나타낸다.


#include <stdio.h>

int main()
{
    int num1 = 1;
    int num2 = 2;
    int num3;

    num3 = (num1 << 2) + (num2 << 1); // +보다 << 연산을 먼저하기 위해 괄호로 묶어줌

    printf("%d\n", num3); // 8

    return 0;
}


  • 즉, (num1 << 2) + (num2 << 1)은 시프트 연산을 ()로 묶었으므로 덧셈보다 먼저 계산된다.

References