🧠 주제

이 문서는 C++에서 사용하는 연산자의 모든 종류와 그 내부 원리를 다룬다.
주된 대상은 다음과 같다:

  • 산술 연산자: 덧셈, 뺄셈, 곱셈, 나눗셈, 나머지
  • 복합 대입 연산자: +=, -=, *=, /=, %=
  • 증감 연산자: ++, --의 전위/후위 사용 차이
  • 시프트 연산자: <<, >>와 signed/unsigned 시의 차이
  • 연산자 우선순위: 괄호를 통한 제어 및 우선순위 규칙
  • 형변환 연산, 정수/실수 혼합 처리
  • 오버플로우/언더플로우 현상과 주의점

특히 비트 수준에서의 연산 결과음수 처리 주의사항, 연산 시 자동 형변환의 원리까지 폭넓고 정확하게 설명되어 있다.


💡 개념

1. 산술 연산자 (Arithmetic Operators)

C++의 기본 수치 연산자로, 두 값을 계산하여 새로운 값을 반환한다.

연산자기능사용 예시결과
+덧셈10 + 313
-뺄셈10 - 37
*곱셈10 * 330
/나눗셈10 / 33 (정수)
%나머지10 % 31
  • / 연산자는 정수형이면 몫만, 실수형이면 소수점까지 반환
  • %는 정수형에만 사용 가능

2. 복합 대입 연산자 (Compound Assignment Operators)

산술 연산과 대입을 한 줄로 처리하는 축약 표현

연산자예시의미
+=a += 5;a = a + 5;
-=a -= 3;a = a - 3;
*=a *= 2;a = a * 2;
/=a /= 2;a = a / 2;
%=a %= 5;a = a % 5;

3. 증감 연산자 (Increment / Decrement)

변수를 1만큼 증가 또는 감소시킬 때 사용

연산자형식의미
++++a전위 증가: 증가 후 사용
++a++후위 증가: 사용 후 증가
----a전위 감소
--a--후위 감소
  • 전위와 후위는 결과가 다르므로 주의가 필요하다.
  • 예: a = hp++;a에는 증가 전 값이 들어감, hp는 이후 증가됨

4. 시프트 연산자 (Shift Operators)

비트를 왼쪽 또는 오른쪽으로 이동시키는 연산자

연산자기능예시결과
<<왼쪽 시프트a << 1a * 2
>>오른쪽 시프트a >> 1a / 2

signed vs unsigned

  • signed 타입에서 >> 연산은 부호 비트가 유지됨 → 산술 시프트
  • unsigned 타입에서는 0이 채워짐논리 시프트

⚠️ 음수 처리 시 반드시 unsigned 타입을 사용하거나, 결과 해석에 주의 필요


5. 연산자 우선순위

여러 연산이 섞여 있을 때 먼저 실행되는 연산자를 정하는 규칙

우선순위 (높음 → 낮음):
1. *, /, %
2. +, -
3. 괄호 ()로 직접 지정 가능

int result = 10 + 5 * 3; // 25
int result2 = (10 + 5) * 3; // 45

6. 정수와 실수 혼합 연산 & 형변환

  • 정수형과 실수형이 섞이면 정수 → 실수로 자동 형변환
  • 명시적 형변환 (float) 등을 사용하면 의도된 정확한 계산 가능
int a = 5;
float b = 2.5;
cout << a + b << endl; // 7.5
int x = 5, y = 2;
float res = (float)x / y; // 2.5

7. 오버플로우 & 언더플로우

개념설명예시
오버플로우최대값 초과 시 최소값으로 순환됨unsigned int max = 4294967295; max += 1; // 0
언더플로우최소값 미만 시 최대값으로 순환됨short s = -32768; s -= 1; // 32767
  • 원인은 2의 보수 표현과 비트 수 제한

📚 용어정리

용어정의
산술 연산자기본 수학 연산 수행 (+, -, *, /, %)
대입 연산자연산 후 결과를 변수에 저장 (=, += 등)
증감 연산자값을 1만큼 증가 또는 감소 (++, --)
복합 연산자산술 연산 + 대입을 한 줄로 작성 (+=, *= 등)
시프트 연산자비트를 좌/우로 이동 (<<, >>)
전위/후위 연산자증가/감소 시점에 따라 결과가 달라짐
오버플로우데이터 최대값 초과 시 0으로 순환
언더플로우최소값 이하 시 최대값으로 순환
산술 시프트부호 비트를 유지한 채 시프트 (signed)
논리 시프트부호 고려 없이 0을 채워 시프트 (unsigned)

💻 코드 분석

1. 산술 연산자 사용 예제

int a = 10, b = 3;
cout << a + b << endl; // 13
cout << a - b << endl; // 7
cout << a * b << endl; // 30
cout << a / b << endl; // 3
cout << a % b << endl; // 1
  • /는 정수형이라 소수점 버림
  • %는 오직 정수형에서만 사용 가능

2. 복합 대입 연산자

int hp = 100;
hp += 5; // hp = 105
hp -= 5; // hp = 100
hp *= 2; // hp = 200
hp /= 2; // hp = 100
  • a += ba = a + b 와 완전히 동일하지만 코드 간결성을 제공

3. 증감 연산자 전위/후위

int hp = 100;
hp++;         // hp = 101 (후위 증가)
int a = hp;   // a = 101
++hp;         // hp = 102 (전위 증가)
  • 후위는 먼저 사용 → 나중에 증가
  • 전위는 먼저 증가 → 그 후 사용

4. 시프트 연산자와 음수 처리

signed char x = -128; // 10000000
x = x >> 1;           // 11000000 → -64

unsigned char y = 128; // 10000000
y = y >> 1;            // 01000000 → 64
  • signed는 부호 유지
  • unsigned는 0 채움

5. 명시적 형변환

int a = 5, b = 2;
float result = (float)a / b; // 2.5
  • 정밀한 계산을 원할 때 형변환 필수

6. 오버플로우

unsigned int max = 4294967295;
max += 1;
cout << max << endl; // 0
  • unsigned는 양수만 표현하므로 최대값 초과 시 0으로 초기화됨

🔑 핵심

  • 연산자는 단순한 기호가 아니라 명확한 동작 원리와 자료형, 비트 구조를 고려한 사용이 필요하다.
  • ++, --, /, %, >> 등의 연산은 자료형에 따라 다르게 해석되며, 특히 signed/unsigned 차이, 정수/실수 차이는 반드시 구분해서 사용해야 한다.
  • 오버플로우, 언더플로우, 형변환 문제는 사소해 보이지만 큰 버그로 이어질 수 있으므로 방어적 코드 작성이 중요하다.
  • 시프트 연산자는 수학 연산을 빠르게 대체할 수 있으며, 비트 단위 최적화, 암호화, ID 생성 등 실무 활용도가 매우 높다.
  • 연산자의 우선순위는 로직 오류의 원인이 되기 쉬우므로, 괄호를 적극적으로 사용하여 명시적으로 제어하는 습관을 들여야 한다.
profile
李家네_공부방

0개의 댓글