산술 연산자는 사칙연산을 다루는 연산자로 가장 기본적이면서 가장 많이 사용되는 연산자이다.
산술 연산자로는 + - * / % 가 있으며 두 개의 피연산자를 요구하는 이항 연산자이다. 산술 연산자의 우선순위는 사칙 연산의 우선 순위와 같다.
| 산술 연산자 | 설명 |
|---|---|
+ |
왼쪽 피연산자에 오른쪽 피연산자를 더한다. |
- |
왼쪽 피연산자에서 오른쪽 피연산자를 뺀다. |
* |
왼쪽 피연산자에 오른쪽 피연산자를 곱한다. |
/ |
왼쪽 피연산자를 오른쪽 피연산자로 나눈 몫을 구한다. |
% |
왼쪽 피연산자를 오른쪽 피연산자로 나눈 후의 나머지를 구한다. |
#include <iostream>
int main()
{
int a = 10;
int b = 3;
std::cout << "a = " << a << ", b = " << b << std::endl;
std::cout << "a + b = " << a + b << std::endl;
std::cout << "a - b = " << a - b << std::endl;
std::cout << "a * b = " << a * b << std::endl;
std::cout << "a / b = " << a / b << std::endl;
std::cout << "a % b = " << a % b << std::endl;
return 0;
}
a = 10, b = 3
a + b = 13
a - b = 7
a * b = 30
a / b = 3
a % b = 1
증감 연산자는 피연산자를 1 씩 증가 또는 감소시킬 때 사용하는 연산자로 피연산자가 하나뿐인 단항 연산자이다.
증감 연산자는 피연산자의 어느 쪽에 위치하는가에 따라 연산 순서 및 결과가 달라진다.
| 연산자 | 설명 |
|---|---|
n++ |
해당 문장을 진행한 후 피연산자의 값을 1 증가시킨다. |
++n |
피연산자의 값을 1 증가시킨 후에 해당 문장을 진행한다. |
n-- |
해당 문장을 진행한 후 피연산자의 값을 1 감소시킨다. |
--n |
피연산자의 값을 1 감소시킨 후에 해당 문장을 진행한다. |
#include <iostream>
int main()
{
int a = 10;
int b = 1;
std::cout << "a = " << a << ", b = " << b << std::endl;
a++;
std::cout << "a = " << a << ", b = " << b << std::endl;
++a;
std::cout << "a = " << a << ", b = " << b << std::endl;
a--;
std::cout << "a = " << a << ", b = " << b << std::endl;
--a;
std::cout << "a = " << a << ", b = " << b << std::endl;
std::cout << std::endl;
std::cout << "a++ + b = " << a++ + b << std::endl; // 코드 진행 후 a = 11
std::cout << "a = " << a << ", b = " << b << std::endl;
std::cout << std::endl;
std::cout << "++a + b = " << ++a + b << std::endl;
std::cout << "a = " << a << ", b = " << b << std::endl;
return 0;
}
a = 10, b = 1
a = 11, b = 1
a = 12, b = 1
a = 11, b = 1
a = 10, b = 1
a++ + b = 11
a = 11, b = 1
++a + b = 13
a = 12, b = 1
대입 연산자는 변수에 값을 대입할 때 사용하는 이항 연산자이다.
| 연산자 | 설명 |
|---|---|
= |
왼쪽 피연산자에 오른쪽 피연산자를 대입한다. |
등호의 왼쪽은 반드시 변수이어야 하고 등호의 오른쪽은 어떠한 수식이라도 가능하다.
#include <iostream>
int main()
{
int num;
num = 5;
std::cout << "num = " << num << std::endl;
num = 1 + 2;
std::cout << "num = " << num << std::endl;
num = 1;
num = num + 1;
std::cout << "num = " << num << std::endl;
return 0;
}
num = 5
num = 3
num = 2
복합 대입 연산자는 += 처럼 대입 연산자와 산술 연산자를 합쳐 놓은 연산자이다.
| 연산자 | 의미 | 연산자 | 의미 |
|---|---|---|---|
x += y |
x = x + y |
x &= y |
x = x & y |
x -= y |
x = x - y |
`x | = y` |
x *= y |
x = x * y |
x ^= y |
x = x ^ y |
x /= y |
x = x / y |
x >>= y |
x = x >> y |
x %= y |
x = x % y |
x <<= y |
x = x << y |
#include <iostream>
int main()
{
int num = 8;
num += 10; // num = num + 10 과 같은 의미입니다.
std::cout << "(num += 10 의 결과) num = " << num << std::endl;
num -= 5; // num = num - 5 과 같은 의미입니다.
std::cout << "(num -= 5 의 결과) num = " << num << std::endl;
num *= 2; // num = num * 2 과 같은 의미입니다.
std::cout << "(num *= 2 의 결과) num = " << num << std::endl;
num /= 5; // num = num / 5 과 같은 의미입니다.
std::cout << "(num /= 5 의 결과) num = " << num << std::endl;
num %= 2; // num = num % 5 과 같은 의미입니다.
std::cout << "(num %= 2 의 결과) num = " << num << std::endl;
}
(num += 10 의 결과) num = 18
(num -= 5 의 결과) num = 13
(num *= 2 의 결과) num = 26
(num /= 5 의 결과) num = 5
(num %= 2 의 결과) num = 1
비교 연산자는 피연산자 사이의 상대적인 크기를 판단하는 연산자로, 왼쪽 피연산자와 오른쪽 피연산자를 비교하여 어느 쪽이 더 큰지, 작은지 또는 서로 같은지를 판단한다.
| 연산자 | 설명 |
|---|---|
== |
왼쪽 피연산자와 오른쪽 피연산자가 같으면 true 를 반환 |
!= |
왼쪽 피연산자와 오른쪽 피연산자가 같지 않으면 true 를 반환 |
> |
왼쪽 피연산자가 오른쪽 피연산자보다 크면 true 를 반환 |
>= |
왼쪽 피연산자가 오른쪽 피연산자보다 크거나 같으면 true 를 반환 |
< |
왼쪽 피연산자가 오른쪽 피연산자보다 작으면 true 를 반환 |
<= |
왼쪽 피연산자가 오른쪽 피연산자보다 작거나 같으면 true 를 반환 |
#include <iostream>
int main()
{
int a = 1;
int b = 2;
std::cout << (a == b) << std::endl;
std::cout << (a != b) << std::endl;
std::cout << (a > b) << std::endl;
std::cout << (a >= b) << std::endl;
std::cout << (a < b) << std::endl;
std::cout << (a <= b) << std::endl;
return 0;
}
0
1
0
0
1
1
논리 연산자는 주어진 논리식을 판단하여 true, false 를 결정하는 연산자이다. AND 연산과 OR 연산은 2개의 피연산자를 갖고, NOT 연산은 1 개의 피연산자를 갖는다.
| 연산자 | 설명 |
|---|---|
&& |
논리식이 모두 true면 true를 반환한다. (논리 AND 연산) |
| ` | |
! |
논리식의 결과가 true면 false를, false면 true를 반환한다. (논리 NOT 연산) |
논리 연산자 동작 결과 (진리표)
| A | B | A && B | A || B | !A |
| --- | --- | --- | --- | --- |
| true | true | true | true | false |
| false | true | false | true | true |
| true | false | false | true | false |
| false | false | false | false | true |
#include <iostream>
int main()
{
int a = 1;
int b = 2;
std::cout << ((a < 2) && (b > 1)) << std::endl; // true && true
std::cout << ((a > 2) || (b < 1)) << std::endl; // false || false
std::cout << ((a > 2) || (b > 1)) << std::endl; // false || true
std::cout << !(a > 0) << std::endl; // !true
return 0;
}
1
0
1
0
비트 연산자는 비트 bit 단위로 논리 연산을 할 때 사용되는 연산자이다.
| --- | --- |


왼쪽 시프트 연산 << 의 경우, 양수, 음수와 관계없이 새롭게 채워지는 비트들은 0 으로 채워지고, 이동으로 인해 밀려나는 왼쪽 비트들은 버려진다.

오른쪽 시프트 연산 >> 의 경우, 양수의 값을 이동시킬 때 새롭게 채워지는 비트들은 0 으로 채워지고, 음수의 값을 이동시킬 때 새롭게 채워지는 비트들은 1 로 채워진다. 이동으로 인해 밀려나는 오른쪽 비트들은 버려진다.

위의 그림에서 범위를 넘어가는 비트 연산은 버려진다고 표현했지만 하드웨어에 따라 다르게 처리되므로 위처럼 범위를 넘어가는 비트 연산의 경우에는 사용하지 않는 것이 좋다.
#include <iostream>
#include <bitset>
int main()
{
char a = 0b00001010; // 0000 1010
char b = 0b00000011; // 0000 0011
char c = 0b11011010; // 1101 1010
std::cout << " ~a : " << std::bitset<8>(~a) << std::endl;;
std::cout << " a & b : " << std::bitset<8>(a & b) << std::endl;
std::cout << " a | b : " << std::bitset<8>(a | b) << std::endl;
std::cout << " a ^ b : " << std::bitset<8>(a ^ b) << std::endl;
std::cout << "a >> 2 : " << std::bitset<8>(a >> 2) << std::endl; // 양수 오른쪽 쉬프트
std::cout << "c >> 2 : " << std::bitset<8>(c >> 2) << std::endl; // 음수 오른쪽 쉬프트
std::cout << "c << 2 : " << std::bitset<8>(c << 2) << std::endl;
return 0;
}
~a : 11110101
a & b : 00000010
a | b : 00001011
a ^ b : 00001001
a >> 2 : 00000010
c >> 2 : 11110110
c << 2 : 01101000
위의 예제들에서 보면 알 수 있듯이 << 연산자의 경우 1칸 이동할때마다 정수의 값이 2배로 커지고, >> 연산자의 경우 1칸 이동할때마다 정수의 값은 반이 된다는 것을 알 수 있다.
이는 상황에 따라 곱셈과 나눗셈을 비트의 이동 연산으로 구할 수 있다는 것을 나타내고, CPU 입장에서는 곱셈과 나눗셈이 비트 이동보다 부담스러운 연산이기 때문에 성능 향상으로 이어질 수 있다.
메모리의 최소 크기 단위는 1 byte 이므로 변수는 적어도 1 byte 이상의 크기를 가진다.
이때 1 byte 는 8 bit 이므로 8가지의 상태를 저장할 수 있다. 반면 1 byte 크기를 가지는 bool 자료형 은 8 bit 중 1 bit 만을 사용하고 7 bit 를 낭비하면서 1가지 상태만을 저장한다. 따라서 비트 플래그(Bit Flag)를 이용하면 bool 자료형보다 훨씬 효율적으로 상태를 저장할 수 있다.