식이 나타낸 일정한 규칙에 따라 계산함
=
- 변수에 값을 대입할 때 사용하는 이항 연산자
- 피연산자들의 결합 방향은 오른쪽에서 왼쪽
- 산술 연산자와 비트 연산자 등을 결합하여 사용하는 복합 대입 연산자가 있음
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 | () 캐스트 | ||||||
왼쪽에서 오른쪽 연결성 | .* | →* | |||||
왼쪽에서 오른쪽 결합성 | * | / | % | ||||
왼쪽에서 오른쪽 연결성 | + | - | |||||
왼쪽에서 오른쪽 연결성 | << | >> | |||||
왼쪽에서 오른쪽 연관성 | < | > | <= | >= | |||
왼쪽에서 오른쪽 연결성 | == | != | |||||
왼쪽에서 오른쪽 연관성 | & | ||||||
왼쪽에서 오른쪽 연관성 | ^ | ||||||
왼쪽에서 오른쪽 연결성 | |||||||
왼쪽에서 오른쪽 연관성 | && | ||||||
왼쪽에서 오른쪽 결합성 | |||||||
오른쪽에서 왼쪽 결합성 | ? : | = | *=, /=, %= | +=, -= | <<=, >>= | &=, | =, ^= |
왼쪽에서 오른쪽 결합성 | , |