의미
연산자 우선순위란, C 언어에서 사용되는 수 많은 연산자들의 연산 순서를 의미한다.
보통 +, -보다 *, / 가 우선이고 비트 연산자 우선순위 정도까지 생각을 하는 분이 많을 것이라고 생각하는데 우리가 코드에서 보는 모든 기호에 우선순위가 부여되어있고 그 우선순위를 이해하다보면 포인터, 배열 등의 개념의 이해에 큰 도움이 될 것이다.
동작 방식
순위 | 명칭 | 연산자 | 결합방향 |
1 | 1차 연산자 | () [] . -> | -> |
2 | 단항 연산자 | + - ! ~ (type) sizeof ++ -- & * | <- |
3 | 승법 연산자 | * / % | -> |
4 | 가법 연산자 | + - | |
5 | Shift 연산자 | << >> | |
6 | 관계 연산자 | < > <= >= | |
7 | 등가 연산자 | == != | |
8 | bit 곱 연산자 | & | |
9 | bit 차 연산자 | ^ | |
10 | bit 합 연산자 | | | |
11 | 논리곱 연산자 | && | |
12 | 논리합 연산자 | || | |
13 | 조건 연산자 | ?: | -> |
14 | 대입 연산자 | = += -= *= /= %= <<= >>= &= |= |
<- |
15 | 순차 연산자 | , | -> |
문제 코드 1. 연산자 우선순위를 나타내려면 괄호를 사용하는 것이 좋다.
출력을 예상해보기
#include <stdio.h>
typedef int bool;
enum { false, true };
int main()
{
int x = 3;
// x 변수의 최하위 비트를 검사하는 경우
x & 1 == 0;
int *p;
int num = 3;
p = #
// p가 가리키는 것을 증가하려는 경우
*p++;
int num = 10;
// num이 10과 같지 않은가를 테스트하는 경우
bool res = !num == 10;
return 0;
}
출력 :
물론, print하는 경우가 없으므로 출력이 되지 않지만 문제가 되는 부분은 3 부분이 있다.
취약점 분석 및 해결 코드 1
분석
(1) x & 1== 0 에서 == 연산자가 우선이다.
(2) *p++ 에서 ++이 *보다 우선이다.
(3) == 보다 !이 우선순위이므로 비교한 결과의 부정을 나타낼 수가 없다.
해결 방법 : 연산자 우선순위를 나타내려면 괄호를 이용하자.
*** 모든 연산자의 우선순위를 외울 수 없으므로 괄호를 통해서 원하는 연산 순위대로 수정하는 것이 좋다.
#include <stdio.h>
typedef int bool;
enum { false, true };
int main()
{
int x = 3;
// x 변수의 최하위 비트를 검사하는 경우
(x & 1) == 0;
int *p;
int num = 3;
p = #
// p가 가리키는 것을 증가하려는 경우
(*p)++;
// num이 10과 같지 않은가를 테스트하는 경우
bool res = !(num == 10);
return 0;
}
POINT
- 연산자 우선순위 표를 참고하고 자주 사용하는 부분은 기억하고 나머지는 자주 참조하자.
- 연산자 우선순위를 좀 알더라도 정확히 괄호를 통해서 확실히 프로그램이 동작하게 하자
참조
EXP00-C. Use parentheses for precedence of operation
wiki.sei.cmu.edu/confluence/display/c/EXP00-C.+Use+parentheses+for+precedence+of+operation
'C, C++ > 표현식' 카테고리의 다른 글
[CERT C/표현식] (5) NULL 체크의 중요성 (0) | 2021.02.03 |
---|---|
[CERT C/표현식] (4) 함수 반환 값의 중요성 (0) | 2021.01.29 |
[CERT C/표현식] (3) 포인터 연산 수행의 중요성 (0) | 2021.01.29 |
[CERT C/표현식] (2) 단축 평가 방식의 중요성 (0) | 2021.01.28 |