C 식은 값을 만드는 표현식이고, 연산자는 그 값을 어떻게 계산할지 정하는 도구입니다. 주요 연산자 그룹을 먼저 훑고, 자주 틀리는 식을 함께 보는 편이 가장 빠릅니다.
- C에서 어떤 연산자 종류가 있는지 빠르게 다시 보고 싶다
- 정수 나눗셈, 증가 연산, 단락 평가, 대입/비교 혼동을 같이 정리하고 싶다
- 우선순위와 평가 순서 때문에 어디서 실수하는지 확인하고 싶다
숏컷 코드
int q = a / b;
double x = (double)a / b;
if (ptr != NULL && *ptr > 0) { process(*ptr); }
if (x == 10) { /* 비교 */ }문법
C에서 자주 다시 보는 연산자 그룹은 보통 아래처럼 나뉩니다.
- 산술:
+ - * / % - 비교:
== != < <= > >= - 논리:
&& || ! - 비트:
& | ^ ~ << >> - 대입:
= += -= *= /= %= - 증감:
++ -- - 조건:
?: - 기타:
sizeof,,
연산자는 종류를 먼저 나눠 보고, 그다음에 실제로 자주 틀리는 식을 같이 보는 편이 정리가 쉽습니다.
정수 나눗셈과 실수 나눗셈
int q = a / b;
double x = (double)a / b;정수끼리 /를 하면 소수 부분이 버려집니다. 평균값, 비율, 퍼센트처럼 실수 결과가 필요하면 계산 전에 한쪽을 double로 올려야 합니다.
전위 증가와 후위 증가
int x = 5;
printf("%d\n", x++); // 5
printf("%d\n", ++x); // 7x++는 현재 값을 먼저 쓰고 나서 증가하고, ++x는 증가한 뒤 값을 씁니다.
비교, 논리, 대입
if (a == b) { }
if (!ready || error) { }
count += 1;비교 연산은 조건문에서 거의 항상 같이 나오고, 논리 연산은 조건을 묶는 역할을 합니다. 대입 연산은 값을 저장하는 쪽이라 비교와 섞이면 바로 실수가 납니다.
if (x = 10) { } /* 대입 */
if (x == 10) { } /* 비교 */이 두 줄이 비슷해 보여도 의미는 완전히 다릅니다. 조건식에서는 =보다 ==를 먼저 의심하는 편이 안전합니다.
단락 평가, 조건 연산자, sizeof
if (ptr != NULL && *ptr > 0) {
process(*ptr);
}
int max = (a > b) ? a : b;
size_t n = sizeof(arr) / sizeof(arr[0]);&&와 ||는 왼쪽만으로 결과가 정해지면 오른쪽을 보지 않습니다. 그래서 NULL 검사 뒤 역참조 같은 패턴이 안전해집니다. ?:는 짧은 값 선택에, sizeof는 타입 크기와 배열 길이 계산에 자주 쓰입니다.
체크포인트
- 정수끼리 계산하면 정수 결과가 나옵니다.
- 비교 연산과 대입 연산은 모양이 비슷해서 가장 자주 헷갈립니다.
- 논리 연산은 조건을 묶고, 단락 평가 덕분에 안전 검사 패턴을 만들 수 있습니다.
- 증가 연산은 값이 쓰이는 시점이 달라서 복잡한 식 안에 섞지 않는 편이 좋습니다.
- 우선순위가 조금이라도 애매하면 괄호를 먼저 씁니다.
- 비트 연산은 산술과 감각이 다르므로 플래그/마스크 카드처럼 따로 보는 편이 낫습니다.
int total = a + b * c;
int total2 = a + (b * c);연산자 우선순위는 외우기보다 괄호로 명시하는 편이 낫습니다. 특히 비트 연산, 비교 연산, 논리 연산이 섞이면 사람이 읽는 우선순위와 실제 우선순위가 쉽게 어긋납니다.
int ok = flags & MASK == 0; /* 읽는 사람 기준으로 헷갈림 */
int safe = ((flags & MASK) == 0); /* 의도 명시 */주의할 점
조건식에서 =와 ==를 혼동하면 비교가 아니라 대입이 됩니다.
if (x = 10) {
/* 대입 결과가 조건으로 쓰임 */
}
if (x == 10) {
/* 비교 */
}=는 대입이고==는 비교입니다.- 복잡한 식 안에
x++, 함수 호출, 대입을 한꺼번에 섞는 건 피하는 편이 좋습니다. - C에서는 "짧게"보다 "평가 순서가 분명한가"가 더 중요합니다.
참고 링크
1 sources