C/C++ 연산자 우선순위 & 결합방향
| 우선순위 | 연산자 | 설명 | 결합방향 |
| 1 | :: | 범위 지정 (C++) | 좌→우 |
| 2 | () [] . -> ++(후위) --(후위) | 함수호출, 배열첨자, 멤버접근, 후위 증감 | 좌→우 |
| 3 | ++(전위) --(전위) +(단항) -(단항) ! ~ (type)(캐스팅) *(역참조) &(주소) sizeof | 전위 증감, 단항 연산, 캐스팅, 역참조/주소 | 우→좌 |
| 4 | .* ->* | 멤버 포인터 (C++) | 좌→우 |
| 5 | * / % | 곱셈, 나눗셈, 나머지 | 좌→우 |
| 6 | + - | 덧셈, 뺄셈(이항) | 좌→우 |
| 7 | << >> | 비트 시프트 | 좌→우 |
| 8 | < <= > >= | 관계 연산자 | 좌→우 |
| 9 | == != | 동등 비교 | 좌→우 |
| 10 | & | 비트 AND | 좌→우 |
| 11 | ^ | 비트 XOR | 좌→우 |
| 12 | | | 비트 OR | 좌→우 |
| 13 | && | 논리 AND | 좌→우 |
| 14 | || | 논리 OR | 좌→우 |
| 15 | ?: | 삼항 조건 연산자 | 우→좌 |
| 16 | = += -= *= /= %= <<= >>= &= ^= |= | 대입 연산자 | 우→좌 |
| 17 | , | 콤마 연산자 | 좌→우 |
헷갈리기 쉬운 것들 예시로 확인
1. 산술 > 비교 > 논리 > 대입 순서
int result = 3 + 5 > 2 && 1 == 1;
// 순서: (3+5) > 2 && (1==1)
// = 8 > 2 && 1==1
// = 1 && 1
// = 1
2. 단항 연산자가 이항보다 우선순위 높음
int a = -3 + 5; // -(3) 먼저 계산 -> -3 + 5 = 2
3. *(역참조/포인터)와 ++가 헷갈리는 대표 사례
int arr[3] = {10, 20, 30};
int* p = arr;
int x = *p++; // *(p++) 로 해석됨 -> 먼저 p 역참조해서 값 가져온 후(10), p를 증가
전위 단항 *와 후위 ++가 같이 있으면, 후위 ++가 더 먼저 적용된 것처럼 보이지만 실제로는 결합방향(우→좌) 규칙 때문에 *(p++)로 묶여. 즉 p를 먼저 증가시키는 게 아니라, p가 가리키는 값을 먼저 읽고(*p), 그 다음에 p 자체를 증가시킴 — 그리고 증가된 p는 다음 문장부터 반영됨.
4. 비트 연산자(&, |, ^)가 비교 연산자보다 우선순위 낮음 — 자주 실수하는 부분
if (x & 1 == 0) { ... } // 의도: x가 짝수인지 확인하고 싶었음
이거 실제로는 x & (1 == 0)으로 해석됨 (==이 &보다 우선순위 높아서). 1 == 0은 0(거짓)이니까 결국 x & 0이 되어 **항상 0(거짓)**이 되는 버그. 반드시 괄호로 명시해야 함:
if ((x & 1) == 0) { ... } // 올바름
5. 삼항 연산자와 대입 연산자 우선순위
int a = 1 > 0 ? 10 : 20; // (1>0) ? 10 : 20 -> a = 10
삼항 연산자(?:)가 대입(=)보다 우선순위가 높아서, 삼항 연산 전체가 먼저 계산된 후 그 결과가 a에 대입됨.
단순 암기가 아닌 문제 만들어서 풀어보는 것이 중요.
'공부' 카테고리의 다른 글
| 우리는 왜 UTF-8을 써야 하는가 (0) | 2026.07.07 |
|---|---|
| 버블정렬 (0) | 2026.07.06 |
| 이스케이프 시퀀스 / C 표준 입출력 (0) | 2026.07.05 |
| 데이터 모델별 비트 차이 (0) | 2026.07.04 |
| 메모리 구조(프로세스 주소공간 전체 구조) (0) | 2026.07.04 |