식이 나타낸 일정한 규칙에 따라 계산함
=
- 변수에 값을 대입할 때 사용하는 이항 연산자
- 피연산자들의 결합 방향은 오른쪽에서 왼쪽
- 산술 연산자와 비트 연산자 등을 결합하여 사용하는 복합 대입 연산자가 있음
int a = 1; // a라는 이름의 바구니를 만들고 안에 1을 넣는다(1을 대입한다)
int b = 2; // b라는 이름의 바구니를 만들고 안에 2를 넣는다(2를 대입한다)
a = b; // a에 b의 값을 넣어라(a = 2, b = 2인 상태)
| 산술 연산자 | 설명 |
|---|---|
| + | 왼쪽의 피연산자에 오른쪽 피연산자를 더함 |
| - | 왼쪽의 피연산자에서 오른쪽 피연산자를 뺌 |
| * | 왼쪽의 피연산자에서 오른쪽의 피연산자를 곱함 |
| / | 왼쪽의 피연산자를 오른쪽의 피연산자로 나눔 |
| % | 왼쪽의 피연산자를 오른쪽의 피연산자로 나눈 후, 그 나머지를 반환 |
int a = 1, b = 1;
a = b + 3; // b에 3을 더한 값을 a에 넣어라 [a = 4, b = 1]
a = b - 3; // b에 3을 뺀 값을 a에 넣어라 [a = -2, b = 1]
a = b * 3; // b에 3을 곱한 값을 a에 넣어라 [a = 3, b = 1]
a = b / 3; // b에 3을 나눈 값을 a에 넣어라 [a = 0, b = 1]
a = b % 3; // b에 3을 나눈 후 나머지 값을 a에 넣어라 [a = 1, b = 1]
a의 값만 계속 바뀌는 이유는, b의 값은 건들지 않으면서도 b와 3과의 연산으로만 이루어지고 이를 a에 대입하는 것이기 때문이다. 또한 나누기 연산에서 a의 값이 0.333… 이 아니고 0인 이유는 두 변수의 자료형이 정수형이기 때문이다. 정수형에서는 소수점을 처리할 수가 없기 때문에 버림하여 대입하면 0이기 때문이다.
| 증감 연산자 | 설명 |
|---|---|
| ++x | [전위] 피연산자의 값을 1 증가시킨 후, 해당 연산을 진행함 |
| x++ | [후위] 먼저 해당 연산을 진행한 후, 피연산자의 값을 1 증가시킴 |
| —x | [전위] 피연산자의 값을 1 감소시킨 후, 해당 연산을 진행 |
| x— | [후위] 먼저 해당 연산을 진행한 후, 피연산자의 값을 1 감소시킴 |
int a = 10;
a = a + 1; // [a = 11]
a++; // [a = 12]
++a; // [a = 13]
a--; // [a = 12]
--a; // [a = 11]
int a = 3;
int b = 5;
int c;
c = ++a + b--; // 보통은 이렇게 사용하진 않겠지만 이해하기 위하여 설정
우선 a 앞에 전위 증가 연산자가 있기 때문에 a의 값을 1 더하여 4로 만든다. 그리고 a + b 연산을 수행하고 이를 c에 넣으면 c의 값은 9가 된다. 이후 b의 후위 감소 연산자를 계산하여 b = 4로 만든다.
최종 상태 : a = 4, b = 4, c = 9
언제 필요한가?
| 비교 연산자 | 설명 |
|---|---|
| == | 왼쪽의 피연산자와 오른쪽의 피연산가 같으면 1을 반환 |
| != | 왼쪽의 피연산자와 오른쪽의 피연산자가 같지 않으면 1을 반환 |
| > | 왼쪽의 피연산자가 오른쪽의 피연산자보다 크면 1을 반환 |
| >= | 왼쪽의 피연산자가 오른쪽의 피연산자보다 크거나 같으면 1을 반환 |
| < | 왼쪽의 피연산자가 오른쪽의 피연산자보다 작으면 1을 반환 |
| <= | 왼쪽의 피연산자가 오른쪽의 피연산자보다 작거나 같으면 1을 반환 |
// a == b : a와 b의 값이 같은가?
bool isSame = a == b; // 같으면 1, 다르면 0
// a != b : a와 b의 값이 다른가?
bool isDifferent = a != b; // 다르면 1, 같으면 0
// a > b : a가 b보다 큰가?
bool isGreater = a > b; // 크면 1, 작으면 0
// a < b : a가 b보다 작은가?
bool isSmaller = a < b; // 작으면 1, 크면 0
비교 연산자를 수행하여 담기는 데이터는 0 또는 1이다. 이는 bool 변수에 담거나 조건문(뒤에 나오는개념)에서 검사하여 조건에 따른 문장을 나누어 실행하고 싶을 때 사용한다. 후자일 경우에는 변수에 담을 필요가 없어 변수명을 지어줄 필요는 없지만, 만약 전자처럼 변수에 담아서 꾸준히 사용하고 싶을 경우 bool 자료형으로 만들어 네이밍은 보통 is로 시작하여 작명한다.
언제 필요한가?
| 논리 연산자 | 설명 |
|---|---|
| && | [AND] 논리식이 모두 참이면 1을 반환 |
| ! | [NOT] 논리식의 결과가 참이면 0을, 거짓이면 1을 반환 |
| A | B | A && B [AND] | A | |
|---|---|---|---|---|
| 1 | 1 | 1 | 1 | 0 |
| 1 | 0 | 0 | 1 | 0 |
| 0 | 1 | 0 | 1 | 1 |
| 0 | 0 | 0 | 0 | 1 |
bool isGuildMaster = false;
bool isAdmin = true;
if (isGuildMaster || isAdmin)
cout << "Access Allowed" << endl;
else
cout << "Access Denied" << endl;
bool hasPosion = true;
bool isMaxHP = true;
if (hasPosion && isMaxHP)
cout << "Can't drink Posion" << endl;
논리 연산자에서 알아야하는 것은 앞의 조건으로만 전체 조건을 확인할 수 있으면 뒤의 조건을 확인하지 않아도 된다. 만약 and 연산을 하는데 앞의 조건이 거짓이라면 and 연산 진리표에서 볼 수 있듯이 하나가 거짓이면 무조건 거짓이기 때문에 바로 거짓이라는 값이 나온다. 또한 or 연산에서 하나라도 참이면 결과는 참이기 때문에 or 연산에서 앞의 조건이 참이면 뒤의 조건은 확인하지 않는다.
언제 필요한가?
| 비트 연산자 | 설명 |
|---|---|
| & | [bit AND] 대응되는 비트가 모두 1이면 1을 반환함 |
| ^ | [bit XOR] 대응되는 비트가 서로 다르면 1을 반환함 |
| ~ | [bit NOT] 비트를 1이면 0으로, 0이면 1로 반전시킴 |
| << | [Left Shift] 지정한 수만큼 비트들을 전부 왼쪽으로 이동시킴 |
| >> | [RIght Shift] 부호를 유지하면서 지정한 수만큼 비트를 전부 오른쪽으로 이동시킴 |
#include <iostream>
using namespace std;
int main() {
int a = 23985;
int b = 12409;
cout << "a : " << bitset<32>(a) << "\n";
cout << "b : " << bitset<32>(b) << "\n";
cout << "& : " << bitset<32>(a&b) << "\n";
cout << "| : " << bitset<32>(a|b) << "\n";
cout << "^ : " << bitset<32>(a^b) << "\n";
cout << "~ : " << bitset<32>(~a) << "\n"; // ~는 단항 연산자
cout << "<<: " << bitset<32>(a<<5) << "\n"; // b의 값이 너무 커서 현재 담겨있는 비트를 다 밀어서 지워버리기 때문에 작은 상수 5 사용
cout << ">>: " << bitset<32>(a>>5) << "\n"; // b의 값이 너무 커서 현재 담겨있는 비트를 다 밀어서 지워버리기 때문에 작은 상수 5 사용
}
// 출력결과
// a : 00000000000000000101110110110001
// b : 00000000000000000011000001111001
// & : 00000000000000000001000000110001
// | : 00000000000000000111110111111001
// ^ : 00000000000000000110110111001000
// ~ : 11111111111111111010001001001110
// <<: 00000000000010111011011000100000
// >>: 00000000000000000000001011101101
#include <iostream>
using namespace std;
int main() {
int a = 2;
int b = 3;
a += b;
cout << "+= : " << a << ", " << b << endl;
a -= b;
cout << "-= : " << a << ", " << b << endl;
a *= b;
cout << "*= : " << a << ", " << b << endl;
a /= b;
cout << "/= : " << a << ", " << b << endl;
a %= b;
cout << "%= : " << a << ", " << b << endl;
a &= b;
cout << "&= : " << a << ", " << b << endl;
a |= b;
cout << "|= : " << a << ", " << b << endl;
a ^= b;
cout << "^= : " << a << ", " << b << endl;
a <<= b;
cout << "<<=: " << a << ", " << b << endl;
a >>= b;
cout << ">>=: " << a << ", " << b << endl;
}
// 출력결과
// += : 5, 3
// -= : 2, 3
// *= : 6, 3
// /= : 2, 3
// %= : 2, 3
// &= : 2, 3
// |= : 3, 3
// ^= : 0, 3
// <<=: 0, 3 // 이미 0인 상태에서 0으로만 된 비트를 좌 우로 옮겨봤자 0이기 때문
// >>=: 0, 3 // 이미 0인 상태에서 0으로만 된 비트를 좌 우로 옮겨봤자 0이기 때문
int a = 2;
int b = 5;
int c = (a > b) ? a : b; // a가 더 크면 a를 c에 대입하고, b가 더 크다면 b를 대입하라.
int d, e; // d와 e를 한 줄에 선언하는 방법(쉼표 연산자 사용)
int size = sizeof(int); // sizeof 연산자 사용 방법
size = sizeof(a);
범위 지정 연산자
멤버 포인터 연산자
두 가지의 연산자
typeid 연산자
//범위 지정 연산자 문법
::식별자
클래스이름::식별자
네임스페이스::식별자
열거체::식별자
//멤버 포인터 연산자 문법
클래스타입객체.*멤버이름
클래스타입객체의포인터->*멤버이름
//typeid
typeid(표현식)
| 우선 순위 및 설명 | 기호 | ||||||
|---|---|---|---|---|---|---|---|
| 결합성 없음 | :: | ||||||
| 왼쪽에서 오른쪽 연결성 | . | → | [], () | (후위)++, | |||
| (후위)— | xx_cast | typeid | |||||
| 오른쪽에서 왼쪽 결합성 | sizeof | ++(전위), | |||||
| —(전위) | ~, ! | -(단항 부정), | |||||
| +(단항 긍정) | &, * | new, | |||||
| delete | () 캐스트 | ||||||
| 왼쪽에서 오른쪽 연결성 | .* | →* | |||||
| 왼쪽에서 오른쪽 결합성 | * | / | % | ||||
| 왼쪽에서 오른쪽 연결성 | + | - | |||||
| 왼쪽에서 오른쪽 연결성 | << | >> | |||||
| 왼쪽에서 오른쪽 연관성 | < | > | <= | >= | |||
| 왼쪽에서 오른쪽 연결성 | == | != | |||||
| 왼쪽에서 오른쪽 연관성 | & | ||||||
| 왼쪽에서 오른쪽 연관성 | ^ | ||||||
| 왼쪽에서 오른쪽 연결성 | |||||||
| 왼쪽에서 오른쪽 연관성 | && | ||||||
| 왼쪽에서 오른쪽 결합성 | |||||||
| 오른쪽에서 왼쪽 결합성 | ? : | = | *=, /=, %= | +=, -= | <<=, >>= | &=, | =, ^= |
| 왼쪽에서 오른쪽 결합성 | , |