C 연산자 우선순위
C 연산자 우선순위 (C Operator Precedence)
어떤 표현식이 어떻게 묶이는지는 연산자 우선순위와 결합 규칙이 정해요. 예를 들어 *p++이 (*p)++로 해석되는지 *(p++)로 해석되는지가 여기서 갈리죠. 이 페이지에서 C 연산자의 우선순위와 결합 규칙을 표로 정리해 볼게요.
출처: cppreference
본문
다음 표는 C 연산자의 우선순위와 결합 규칙(associativity)을 나열해요. 연산자는 위에서 아래로 갈수록 우선순위가 낮아져요.
| 우선순위 | 연산자 | 설명 | 결합 규칙 |
|---|---|---|---|
| 1 | ++ -- |
접미사/후위 증가·감소 | 왼쪽→오른쪽 |
() |
함수 호출 | ||
[] |
배열 첨자 | ||
. |
구조체·공용체 멤버 접근 | ||
-> |
포인터를 통한 구조체·공용체 멤버 접근 | ||
(type){list} |
복합 리터럴 (C99) | ||
| 2 | ++ -- |
접두사/전위 증가·감소 [^1] | 오른쪽→왼쪽 |
+ - |
단항 더하기·빼기 | ||
! ~ |
논리 NOT·비트 NOT | ||
(type) |
캐스트 | ||
* |
간접(역참조) | ||
& |
주소 연산 | ||
sizeof |
크기 연산 [^2] | ||
_Alignof |
정렬 요구사항 (C11) | ||
| 3 | * / % |
곱셈·나눗셈·나머지 | 왼쪽→오른쪽 |
| 4 | + - |
덧셈·뺄셈 | |
| 5 | << >> |
비트 왼쪽·오른쪽 시프트 | |
| 6 | < <= |
관계 연산자 < 및 ≤ | |
> >= |
관계 연산자 > 및 ≥ | ||
| 7 | == != |
관계 연산자 = 및 ≠ | |
| 8 | & |
비트 AND | |
| 9 | ^ |
비트 XOR (배타적 or) | |
| 10 | | |
비트 OR (포함적 or) | |
| 11 | && |
논리 AND | |
| 12 | || |
논리 OR | |
| 13 | ?: |
삼항 조건 [^3] | 오른쪽→왼쪽 |
| 14 [^4] | = |
단순 할당 | |
+= -= |
합·차에 의한 할당 | ||
*= /= %= |
곱·몫·나머지에 의한 할당 | ||
<<= >>= |
비트 왼쪽·오른쪽 시프트에 의한 할당 | ||
&= ^= |= |
비트 AND·XOR·OR에 의한 할당 | ||
| 15 | , |
콤마 | 왼쪽→오른쪽 |
[^1]: 전위 ++와 --의 피연산자는 타입 캐스트일 수 없어요. 이 규칙은 문법상으로 어떤 표현식들을 금지하는데, 어차피 그 표현식들은 의미상으로도 유효하지 않아요. 일부 컴파일러는 이 규칙을 무시하고 유효하지 않음을 의미적으로 검출해요.
[^2]: sizeof의 피연산자는 타입 캐스트일 수 없어요: sizeof(int) * p 표현식은 (sizeof(int)) * p로 명확히 해석되지, sizeof((int) * p)로는 해석되지 않아요.
[^3]: 조건 연산자의 중간 표현식(?와 : 사이)은 마치 괄호로 감싼 것처럼 해석돼요. 즉 ?:에 대한 상대적 우선순위는 무시돼요.
[^4]: 할당 연산자의 왼쪽 피연산자는 단항(레벨 2, 비-캐스트) 표현식이어야 해요. 이 규칙은 문법상으로 어떤 표현식들을 금지하는데, 어차피 그 표현식들은 의미상으로도 유효하지 않아요. 많은 컴파일러는 이 규칙을 무시하고 유효하지 않음을 의미적으로 검출해요. 예를 들어 e = a < d ? a++ : a = d는 이 규칙 때문에 파싱될 수 없는 표현식이에요. 하지만 많은 컴파일러는 이 규칙을 무시하고 e = (((a < d) ? (a++) : a) = d)로 파싱한 다음, 의미상 유효하지 않으므로 오류를 내요.
표현식을 파싱할 때, 어떤 행에 나열된 연산자는 그보다 아래 행에 있는 어떤 연산자보다 자기 인자에 더 강하게(마치 괄호로 감싼 것처럼) 결합돼요. 예를 들어 *p++은 *(p++)로 해석되지, (*p)++로 해석되지 않아요.
같은 셀에 있는 연산자(한 셀에 여러 행의 연산자가 나열될 수 있어요)는 같은 우선순위로, 주어진 방향으로 평가돼요. 예를 들어 a = b = c는 오른쪽→왼쪽 결합 때문에 a = (b = c)로 해석되지, (a = b) = c로 해석되지 않아요.
참고 사항 (Notes)
우선순위와 결합 규칙은 평가 순서(order of evaluation)와는 독립적인 개념이에요.
표준 자체는 우선순위 레벨을 명시하지 않아요. 그것들은 문법에서 파생돼요.
C++에서는 조건 연산자가 할당 연산자와 같은 우선순위를 가지며, 전위 ++·--와 할당 연산자는 피연산자에 대한 제약이 없어요.
결합 규칙 명시는 단항 연산자에는 중복되고 완전성을 위해서만 보여져요: 단항 전위 연산자는 항상 오른쪽→왼쪽으로 결합하고(sizeof ++*p는 sizeof(++(*p))), 단항 후위 연산자는 항상 왼쪽→오른쪽으로 결합해요(a[1][2]++은 ((a[1])[2])++). 결합 규칙은 단항 후위 연산자 그룹에 묶여 있음에도 멤버 접근 연산자에 의미가 있다는 점을 주의해요: a.b++는 (a.b)++로 해석되지 a.(b++)로 해석되지 않아요.