우선순위 | 연산자 | 설명 | 결합방향 |
---|---|---|---|
1 | :: | Scope resolution (범위 확인) | 좌 → 우 |
2 | ++ -- | 후위 증가와 감소 | |
() | 함수호출 | ||
[] | 배열 첨자 | ||
. | 참조로 요소 선택 | ||
-> | 포인터를 통해 요소 선택 | ||
3 | ++ -- | 전위 증가와 감소 | 우 → 좌 |
+ − | 단항 덧셈, 뺄셈 | ||
! ~ | 논리 NOT, 비트단위 NOT | ||
(type) | 타입 캐스트 | ||
* | 역참조 | ||
& | 주소값 | ||
sizeof | Size-of 연산자 | ||
new , new[] | 동적 메모리 할당 | ||
delete , delete[] | 동적 메모리 해제 | ||
4 | .* ->* | 멤버 접근 | 좌 → 우 |
5 | * / % | 곱셈, 나눗셈, 나머지 | |
6 | + − | 더하기, 빼기 | |
7 | << >> | 비트 왼쪽 쉬프트와 오른쪽 쉬프트 | |
8 | < <= | 관계 연산자 < 와 ≤ | |
> >= | 관계 연산자 > 와 ≥ | ||
9 | == != | 관계 = 와 ≠ | |
10 | & | 비트 AND | |
11 | ^ | 비트 XOR (exclusive or) | |
12 | | | 비트 OR (inclusive or) | |
13 | && | 논리 AND | |
14 | || | 논리 OR | |
15 | ?: | 삼항연산자 | 우 → 좌 |
= | 직접 할당 (C++ 클래스를 위해 기본 제공) | ||
+= −= | 합과 차 할당 | ||
*= /= %= | 곱, 몫, 나머지 할당 | ||
<<= >>= | 비트 왼쪽 쉬프트와 오른쪽 쉬프트 후 할당 | ||
&= ^= |= | 비트연산 AND, XOR, OR 연산 후 할당 | ||
16 | throw | (예외를 위한)Throw 연산자 | |
17 | , | 콤마 | 좌 → 우 |
숫자가 낮을수록 먼저 계산한다. (연산자 우선순위 표)
연산자 우선순위때문에 코딩미스가 자주 나타나곤 한다. 이제까지 코딩하면서 이런 우선순위때문에 ~얻거나 잃은~ 겪어본 것들을 적어보고자 한다.
1. && 나 || 같은 경우에는 좌에서 우로 연산을 살피기 때문에 런타임 오류(divide by zero, out of range 등)을 예상하여 막을 수 있다.
예를 들면, if(n >= 0 && arr[n] == 1) return 0; 과 같은 코드는 n이 음수일 때는 n >= 0 이 false 이므로 더 이상 조건을 확인하지 않는다. 즉, arr[음수] 인 경우가 없으므로 out of range는 일어나지 않는다. OR연산인 || 역시 중간에 true인 조건이 확인되면 마찬가지로 더 이상 확인하지 않는다.
2. << 과 같은 쉬프트 연산은 사칙연산보다 우선순위가 낮기 때문에 $2^n$ 꼴을 쉬프트로 표현하려면 괄호를 적절히 사용해야한다.
printf("%d", 1<<2+1); 의 출력값은 5가 아닌 8이다.
3. printf는 우에서 좌로 해석한다. (단, C99에서. 이 링크에 의하면, C++에는 순서가 정의되어 있지 않고 컴파일러의 최적화에 따라 다르다고 한다.) 아래 코드의 출력값을 예상해보자.
main(){ int a=1, b=8, c=4; printf("%d %d %d", ++a+c, b/a, b*c++); }결과는 6 4 32 가 아닌 7 8 32이다.
그 이유는 printf 함수는 가변 인자를 받아서 인자의 개수를 모르기 때문이다.
4. 타입 캐스팅은 자료형이 작은 쪽에서 큰 쪽으로 일어난다.
- int + int = int
- long long + int = long long
- ex) long long r = 15 + INT_MAX 는 오버플로우지만, long long r = 15LL + INT_MAX 는 잘 들어간다.
- int + double = double
- ex) int를 double로 변환할 때 쓰면 편하다. (int)50+(double)0.0 은 (double)50.0로 변환된다.
5. 연산의 우선순위는 분명 존재한다. 하지만 잘 작동할 수 있다.
격자무늬를 표현하는 r%2^c%2 라는 코드는 XOR(^)의 우선순위가 mod(%)보다 낮음에도 (r%2)^(c%2) 처럼 잘 작동한다.
3*k++ 과 같이 모호한 코드는 작성하지 않는 것이 가장 좋은 방법이다.
마지막으로, 이 모든 내용은 컴파일러마다 다를 수 있다. 그리고 명시적인 표현의 여부에 따라 다를 수 있다.
작성된 코드가 의도와 같게 작동하지 않을 때, '이럴 수도 있다' 정도의 지식으로만 참고하면 좋을 것 같다.
잘못된 내용이 있다면 지적해주시면 감사하겠습니다.
댓글 없음:
댓글 쓰기