C 언어 연산자 우선순위와 결합 규칙 | 이해하고 버그를 방지하는 방법

1. 소개

C 언어에서 연산자의 우선순위는 프로그램의 동작을 정확히 이해하고, 의도한 대로 결과를 얻기 위해 중요합니다. 특히, 연산자의 평가 순서를 오해하면, 의도하지 않은 결과나 버그가 발생할 가능성이 높아집니다. 이 기사에서는 C 언어의 주요 연산자 우선순위와 결합 규칙에 대해 자세히 설명하고, 구체적인 예를 들어 그 이해를 깊게 합니다.

2. 연산자의 종류와 기본적인 사용법

2.1 산술 연산자

산술 연산자는 수치 계산을 수행하기 위한 기본 연산자입니다. 이러한 연산자는 프로그램 내에서 자주 사용되므로 기본을 확실히 이해하는 것이 중요합니다.
  • + (덧셈): 두 개의 수치를 더합니다.
  • - (뺄셈): 두 개의 수치를 뺍니다.
  • * (곱셈): 두 개의 수치를 곱합니다.
  • / (나눗셈): 두 개의 수치를 나눕니다 (정수 간 나눗셈에서는 소수점 이하가 버려집니다).
  • % (나머지): 나눗셈의 나머지를 구합니다.
예:
int a = 10, b = 3;
int sum = a + b;  // 13
int diff = a - b; // 7
int prod = a * b; // 30
int quot = a / b; // 3
int rem = a % b;  // 1

2.2 비교 연산자

비교 연산자는 두 값을 비교하여 결과를 참(1) 또는 거짓(0)으로 반환합니다. 조건 분기와 루프에서 자주 사용됩니다.
  • > (크다): 왼쪽 값이 오른쪽보다 크면 참.
  • < (작다): 왼쪽 값이 오른쪽보다 작으면 참.
  • >= (크거나 같다): 왼쪽 값이 오른쪽 이상이면 참.
  • <= (작거나 같다): 왼쪽 값이 오른쪽 이하이면 참.
  • == (같다): 좌우 값이 같으면 참.
  • != (같지 않다): 좌우 값이 다르면 참.
int a = 5, b = 10;
if (a < b) {
    printf("a는 b보다 작습니다
");  // 표시된다
}

3. 연산자 우선순위와 결합 규칙

3.1 연산자 우선순위

연산자 우선순위는 여러 연산자가 포함된 식에서 어떤 것이 먼저 평가되는지를 결정합니다. 아래는 C 언어에서의 연산자 우선순위 목록 중 일부입니다. 우선순위가 높은 연산자부터 순서대로 나열했습니다.
우선순위연산자설명
1() [] -> .함수 호출, 배열 접근, 포인터 멤버
2++ --후위 증가·감소
3++ --전위 증가·감소, 부호 연산
4* / %곱셈, 나눗셈, 나머지
5+ -덧셈, 뺄셈
6<< >>비트 시프트
7< <= > >=비교 연산자
8== !=동등, 부등
9&비트 AND
10^비트 XOR
11|비트 OR
12&&논리곱 (AND)
13||논리합 (OR)
14? :조건 연산자
15= += -=대입, 복합 대입
16,쉼표 연산자

3.2 결합 규칙

결합 규칙은 같은 우선순위의 연산자가 여러 개 있을 때 어느 방향에서 평가되는지를 결정합니다. 대부분의 연산자는 좌결합이지만, 몇몇 연산자(예: 대입 연산자, 조건 연산자)는 우결합입니다.
  • 좌결합: *, +, - 등 연산자는 왼쪽에서 오른쪽으로 평가됩니다.
  • 우결합: 대입 연산자와 조건 연산자 ? :는 오른쪽에서 왼쪽으로 평가됩니다.
int a = 5, b = 10, c = 15;
int result = a - b + c;  // 좌결합 (a - b) + c = 0

4. 특정 연산자에 대한 우선순위 주의점

4.1 논리 연산자

논리곱(&&)과 논리합(||)은 조건식을 결합할 때 사용하지만, &&||보다 우선순위가 높기 때문에 다음과 같은 코드에서는 주의가 필요합니다。
int a = 1, b = 0, c = 1;
if (a && b || c) {
    printf("Truen");  // 표시됨
}
이 예에서는 a && b가 먼저 평가되고, 그 결과가 c와 논리합(||)으로 결합됩니다. 올바른 순서로 평가되도록 하려면 괄호를 사용하여 명시적으로 순서를 지정합니다。
if ((a && b) || c) {
    // 보다 명확한 평가
}

4.2 비트 연산자

비트 연산자(&, |, ^)는 비트 단위로 작업을 수행하지만, 산술 연산자나 비교 연산자보다 낮은 우선순위를 가지므로 식이 복잡해지는 경우 주의가 필요합니다。
int x = 5;  // 0101
int y = 3;  // 0011
int result = x & y;  // 0001 (비트 곱)

5. 실제 프로그램 예시

연산자의 우선순위가 오해되기 쉬운 프로그램 예시를 소개합니다. 다음 예에서는 ||&&의 평가 순서가 혼동되는 경우가 많습니다.
#include <stdio.h>
int main() {
    int a = 0, b = 1;
    if (a == 0 || a == 1 && b == 0) {
        printf("Truen");  // 표시됨
    }
    return 0;
}
이 예에서는 a == 1 && b == 0이 먼저 평가되지만, 의도하지 않은 결과가 나올 가능성이 있습니다. 올바른 결과를 얻기 위해서는 괄호를 사용하여 평가 순서를 명시합니다.
if ((a == 0 || a == 1) && b == 0) {
    printf("Truen");
}

6. 결론

C 언어에서 연산자의 우선순위는 프로그램의 올바른 동작에 필수적입니다. 복잡한 식을 다룰 때는 우선순위와 결합 규칙을 이해하고, 괄호를 적절히 사용하여 순서를 명시함으로써 의도치 않은 버그를 방지할 수 있습니다. 연산자 우선순위에 주의를 기울이면 보다 안전하고 효율적인 프로그래밍을 구현할 수 있을 것입니다.
年収訴求