Skip to content

3. 연산자(Operator)


1. 키워드

  • 연산자(Operator)
  • 산술 연산자(Arithmetic Operator)
  • 대입 연산자(Assignment Operator)
  • 증감 연산자(Increment and Decrement Operator)
  • 비교 연산자(Comparison Operator)
  • 논리 연산자(Logical Operator)
  • 비트 연산자(bitwise Operator)
  • 삼항 연산자(Ternary Operator), ,(콤마 연산자), sizeof 연산자
  • ::(범위 지정 연산자), .*->*(멤버 포인터 연산자), typeid 연산자


2. 산술 연산자

  • 산술 연산자는 사칙연산을 다루는 기본적이면서도 가장 많이 사용되는 연산자이다.
  • 산술 연산자는 모두 두 개의 피연산자를 가지는 이항 연산자이며, 피연산자들의 결합 방향은 왼쪽에서 오른쪽이다.


#include <iostream>
using namespace std;

int main() {
    int num1 = 10;
    int num2 = 4;

    cout << "+ 연산자에 의한 결괏값은 " << num1 + num2 << "입니다." << endl;
    cout << "- 연산자에 의한 결괏값은 " << num1 - num2 << "입니다." << endl;
    cout << "* 연산자에 의한 결괏값은 " << num1 * num2 << "입니다." << endl;
    cout << "/ 연산자에 의한 결괏값은 " << num1 / num2 << "입니다." << endl;
    cout << "% 연산자에 의한 결괏값은 " << num1 % num2 << "입니다." << endl;

    return 0;
}

// + 연산자에 의한 결괏값은 14입니다.
// - 연산자에 의한 결괏값은 6입니다.
// * 연산자에 의한 결괏값은 40입니다.
// / 연산자에 의한 결괏값은 2입니다.
// % 연산자에 의한 결괏값은 2입니다.


1) 연산자 우선순위와 결합 방향

  • 연산자의 우선순위는 수식 내에 여러 연산자가 함께 등장할 때, 어느 연산자가 먼저 처리될 것인가를 결정한다.


  • 다음 그림은 가장 높은 우선순위를 가지고 있는 ()(괄호 연산자)를 사용하여 연산자의 처리 순서를 변경하는 것을 보여준다.


001


  • 연산자의 결합 방향은 수식 내에 우선순위가 같은 연산자가 둘 이상 있을 때, 먼저 어느 연산을 수행할 것인가를 결정한다.


002


3. 대입 연산자

  • 대입 연산자는 변수에 값을 대입할 때 사용하는 이항 연산자이며, 피연산자들의 결합 방향은 오른쪽에서 왼쪽이다.
  • 또한 산술 연산자와 결합한 다양한 복합 대입 연산자가 존재한다.


#include <iostream>
using namespace std;

int main() {
    int num1 = 8;
    int num2 = 8;
    int num3 = 8;

    num1 = num1 + 5;
    num2 += 5;
    num3 = +5;

    cout << "- 연산자에 의한 결괏값은 " << num1 << "입니다." << endl;
    cout << "+= 연산자에 의한 결괏값은 " << num2 << "입니다." << endl;
    cout << "=+ 연산자에 의한 결괏값은 " << num3 << "입니다." << endl;

    return 0;
}

// - 연산자에 의한 결괏값은 13입니다.
// += 연산자에 의한 결괏값은 13입니다.
// =+ 연산자에 의한 결괏값은 5입니다.


4. 증감 연산자

  • 증감 연산자는 피연산자를 1씩 증가 혹은 감소시킬 때 사용하는 연산자이다.
  • 이 연산자는 피연산자가 단 하나뿐인 단항 연산자이다.
  • 증감 연산자는 해당 연산자가 피연산자의 어느 쪽에 위치하는가에 따라 연산의 순서 및 결과가 달라진다.


#include <iostream>
using namespace std;

int main() {
    int num1 = 8;
    int num2 = 8;
    int result1, result2;

    result1 = --num1 + 5;
    result2 = num2-- + 5;

    cout << "전위 감소 연산자에 의한 결괏값은 " << result1 << "이고,변수의 값은 " << num1 << "로 변했습니다." << endl;
    cout << "후위 감소 연산자에 의한 결괏값은 " << result2 << "이고, 변수의 값은 " << num2 << "로 변했습니다." << endl;

    return 0;
}

// 전위 감소 연산자에 의한 결괏값은 12이고,변수의 값은 7로 변했습니다.
// 후위 감소 연산자에 의한 결괏값은 13이고, 변수의 값은 7로 변했습니다.


  • 첫 번째 연산은 변수 num1의 값을 먼저 1 감소시킨 후에 나머지 연산을 수행한다.
  • 하지만 두 번째 연산에서는 먼저 모든 연산을 마친 후에 변수 num2의 값을 1 감소시킨다.
  • 따라서 변수 num2의 감소 연산자는 전체 연산에 어떠한 영향도 미치지 않는다.


1) 증감 연산자의 연산 순서

  • 증감 연산자는 피연산자의 어느 쪽에 위치하는가에 따라 연산의 순서가 달라진다.


  • 다음의 코드는 증감 연산자의 연산 순서를 보여주는 것이다.


#include <iostream>
using namespace std;

int main() {
    int x = 10;
    int y = x-- + 5 + --x;

    cout << "변수 x의 값은 " << x << "이고, 변수 y의 값은 " << y << "로 변했습니다." << endl;

    return 0;
}

// 변수 x의 값은 8이고, 변수 y의 값은 23로 변했습니다.


  • 다음 그림은 위의 코드에서 수행되는 연산의 순서를 보여준다.


002


  • ①번에서 첫 번째 감소 연산자는 피연산자의 뒤쪽에 위치하므로, 덧셈 연산이 먼저 수행된다.
  • ②번에서 덧셈 연산이 수행된 후에 감소 연산이 수행된다. (x의 값: 9)
  • ③번에서 두 번째 감소 연산자는 피연산자의 앞쪽에 위치하므로, 덧셈 연산보다 먼저 수행된다. (x의 값: 8)
  • ④번에서 감소 연산이 수행된 후에 덧셈 연산이 수행된다.
  • ⑤번에서 마지막으로 변수 y에 결괏값의 대입 연산이 수행된다. (y의 값: 23)


5. 비교 연산자

  • 비교 연산자는 피연산자 사이의 상대적인 크기를 판단하는 연산자이다.
  • 비교 연산자는 왼쪽의 피연산자와 오른쪽의 피연산자를 비교하여, 어느 쪽이 더 큰지, 작은지, 또는 서로 같은지를 판단한다.
  • 비교 연산자는 모두 두 개의 피연산자를 가지는 이항 연산자이며, 피연산자들의 결합 방향은 왼쪽에서 오른쪽이다.


#include <iostream>
using namespace std;

int main() {
    int num1 = 3;
    int num2 = 7;

    cout << "!= 연산자에 의한 결괏값은 " << (num1 != num2) << "입니다." << endl;
    cout << ">= 연산자에 의한 결괏값은 " << (num1 >= num2) << "입니다." << endl;

    return 0;
}

// != 연산자에 의한 결괏값은 1입니다.
// >= 연산자에 의한 결괏값은 0입니다.


6. 논리 연산자

  • 논리 연산자는 주어진 논리식을 판단하여, 참(true)과 거짓(false)을 결정하는 연산자이다.
  • &&(AND 연산자)와 ||(OR 연산자)는 두 개의 피연산자를 가지는 이항 연산자이며, 피연산자들의 결합 방향은 왼쪽에서 오른쪽이다.
  • !(NOT 연산자)는 피연산자가 단 하나뿐인 단항 연산자이며, 피연산자의 결합 방향은 오른쪽에서 왼쪽이다.


#include <iostream>
using namespace std;

int main() {
    int num1 = 3;
    int num2 = -7;
    bool result1, result2;

    result1 = (num1 > 0) && (num1 < 5);
    result2 = (num2 < 0) || (num2 > 10);

    cout << "&& 연산자에 의한 결괏값은 " << result1 << "입니다." << endl;
    cout << "|| 연산자에 의한 결괏값은 " << result2 << "입니다." << endl;
    cout << " ! 연산자에 의한 결괏값은 " << !result2 << "입니다." << endl;

    return 0;
}

// && 연산자에 의한 결괏값은 1입니다.
// || 연산자에 의한 결괏값은 1입니다.
//  ! 연산자에 의한 결괏값은 0입니다.


7. 비트 연산자

  • 비트 연산자는 논리 연산자와 비슷하지만, 비트 단위로 논리 연산을 할 때 사용하는 연산자이다.
  • 또한, 비트 단위로 왼쪽이나 오른쪽으로 전체 비트를 이동하거나, 1의 보수를 만들 때도 사용된다.


  • 다음 그림은 &(비트 AND 연산자)의 동작을 나타낸다.
  • 이처럼 &는 대응되는 두 비트가 모두 1일 때만 1을 반환하며, 다른 경우는 모두 0을 반환한다.


004


  • 다음 그림은 |(비트 OR 연산자)의 동작을 나타낸다.
  • 이처럼 |는 대응되는 두 비트 중 하나라도 1이면 1을 반환하며, 두 비트가 모두 0일 때만 0을 반환한다.


005


  • 다음 그림은 ^(비트 XOR 연산자)의 동작을 나타낸다.
  • 이처럼 ^는 대응되는 두 비트가 서로 다르면 1을 반환하고, 서로 같으면 0을 반환한다.


005


  • 다음 그림은 ~(비트 NOT 연산자)의 동작을 나타낸다.
  • 이처럼 ~는 해당 비트가 1이면 0을 반환하고, 0이면 1을 반환한다.


006


  • 다음의 코드는 ~<<, >>(시프트 연산자)를 보여주는 것이다.


#include <iostream>
using namespace std;

int main() {
    int num1 = 15;
    int num2 = 8;

    cout << "~ 연산자에 의한 결괏값은 " << (~num1) << "입니다." << endl;
    cout << "<< 연산자에 의한 결괏값은 " << (num2 << 2) << "입니다." << endl;
    cout << ">> 연산자에 의한 결괏값은 " << (num2 >> 2) << "입니다." << endl;

    return 0;
}

// ~ 연산자에 의한 결괏값은 -16입니다.
// << 연산자에 의한 결괏값은 32입니다.
// >> 연산자에 의한 결괏값은 2입니다.


  • <<는 지정한 수만큼 피연산자의 모든 비트를 전부 왼쪽으로 이동시켜 준다.
  • 그런데 결과를 살펴보면 한 비트씩 왼쪽으로 이동할 때마다 2배씩 증가한다는 사실을 알 수 있다.
  • 또한, >>는 지정한 수만큼 피연산자의 모든 비트를 전부 오른쪽으로 이동시켜 준다.
  • 그런데 결과를 살펴보면 한 비트씩 오른쪽으로 이동할 때마다 2배씩 감소한다는 사실을 알 수 있다.


8. 기타 연산자

1) 삼항 연산자

  • 삼항 연산자는 C++에서 유일하게 피연산자를 세 개나 가지는 조건 연산자이다.


  • 삼항 연산자의 문법은 다음과 같다.


조건식 ? 반환값1 : 반환값2


  • ?(물음표) 앞의 조건식에 따라 결괏값이 참(true)이면 반환값1을 반환하고, 결괏값이 거짓(false)이면 반환값2를 반환한다.


#include <iostream>
using namespace std;

int main() {
    int num1 = 11;
    int num2 = 10;
    int result;

    result = (num1 < num2) ? num1 : num2;

    cout << "둘 중에 더 작은수는 " << result << "입니다." << endl;

    return 0;
}

// 둘 중에 더 작은수는 10입니다.


2) ,(콤마 연산자)

  • ,는 얼핏 연산자가 아닌 것처럼 보이지만 다양한 용도로 사용되는 연산자이다.
  • 이 연산자는 어떠한 연산을 수행하는 것이 아닌 다음과 같은 상황에서 사용된다.


1] 두 연산식을 하나의 연산식으로 나타내고자 할 때

2] 둘 이상의 인수를 함수로 전달하고자 할 때


#include <iostream>
using namespace std;

int main() {
    int num1 = 15, num2 = 8;

    cout << "첫 번째 수는 " << num1 << "이고, 두 번째 수는 " << num2 << "입니다." << endl;

    return 0;
}

// 첫 번째 수는 15이고, 두 번째 수는 8입니다.


  • 위의 코드에서 ,는 둘 이상의 변수를 동시에 선언하기 위해서 사용되었다.


3) sizeof 연산자

  • 사용자의 컴퓨터 환경에 따라 타입에 할당되는 메모리의 크기가 달라질 수 있다.
  • sizeof 연산자는 단항 연산자로 피연산자의 크기를 바이트 단위로 반환한다.
  • 이 연산자의 피연산자로는 타입뿐만 아니라 변수나 상수도 올 수 있다.
  • sizeof 연산자에 변수나 상수가 피연산자로 전달되면, 해당 변수나 상숫값에 해당하는 타입의 크기를 반환한다.


#include <iostream>
using namespace std;

int main() {
    cout << "char 타입 데이터에 할당되는 메모리의 크기는 " << sizeof(char) << "바이트입니다." << endl;
    cout << "short 타입 데이터에 할당되는 메모리의 크기는 " << sizeof(short) << "바이트입니다." << endl;
    cout << "int 타입 데이터에 할당되는 메모리의 크기는 " << sizeof(int) << "바이트입니다." << endl;
    cout << "long 타입 데이터에 할당되는 메모리의 크기는 " << sizeof(long) << "바이트입니다." << endl;
    cout << "long long 타입 데이터에 할당되는 메모리의 크기는 " << sizeof(long long) << "바이트입니다." << endl;
    cout << "float 타입 데이터에 할당되는 메모리의 크기는 " << sizeof(float) << "바이트입니다." << endl;
    cout << "double 타입 데이터에 할당되는 메모리의 크기는 " << sizeof(double) << "바이트입니다." << endl;
    cout << "long double 타입 데이터에 할당되는 메모리의 크기는 " << sizeof(long double) << "바이트입니다." << endl;

    return 0;
}

// char 타입 데이터에 할당되는 메모리의 크기는 1바이트입니다.
// short 타입 데이터에 할당되는 메모리의 크기는 2바이트입니다.
// int 타입 데이터에 할당되는 메모리의 크기는 4바이트입니다.
// long 타입 데이터에 할당되는 메모리의 크기는 8바이트입니다.
// long long 타입 데이터에 할당되는 메모리의 크기는 8바이트입니다.
// float 타입 데이터에 할당되는 메모리의 크기는 4바이트입니다.
// double 타입 데이터에 할당되는 메모리의 크기는 8바이트입니다.
// long double 타입 데이터에 할당되는 메모리의 크기는 8바이트입니다.


  • sizeof 연산자를 통해 현재 사용하는 컴퓨터 환경에서의 타입 크기를 알아볼 수 있다.


9. C++ 연산자

  • C++에서는 C의 모든 연산자를 포함하고 있으며, 몇몇 새로운 연산자도 추가하고 있다.
  • C++에서 새롭게 추가된 대표적인 연산자는 다음과 같다.


1] ::(범위 지정 연산자)

2] .*->*(멤버 포인터 연산자)

3] typeid 연산자


1) ::(범위 지정 연산자)

  • C++에서 가장 우선순위가 높은 연산자는 바로 ::이다.
  • ::는 여러 범위에서 사용된 식별자(Identifier)를 식별하고 구분하는 데 사용하는 연산자이다.
  • 이러한 식별자로는 변수, 함수 또는 열거체가 올 수 있다.
  • ::를 변수의 이름 앞에 붙이면 해당 변수는 전역으로 사용하라는 의미로 쓰이게 된다.
  • 또한, 클래스에 이 연산자를 사용하면 네임스페이스 멤버를 식별하거나, 클래스의 정적 멤버를 호출할 수 있다.


  • C++에서 ::를 사용하기 위한 문법은 다음과 같다.


1. ::식별자
2. 클래스이름::식별자
3. 네임스페이스::식별자
4. 열거체::식별자


2) .*->*(멤버 포인터 연산자)

  • C++에서는 .*->*를 사용하여 클래스의 멤버를 가리키는 포인터를 정의할 수 있다.
  • 이러한 .*->*는 다음과 같이 두 가지 형태로 사용한다.


1] 왼쪽의 피연산자가 클래스 타입의 객체인 경우: .*

2] 왼쪽의 피연산자가 클래스 타입의 객체를 가리키는 포인터인 경우: ->*


3) typeid 연산자

  • C++에서는 typeid 연산자를 사용하여 객체의 타입에 관한 정보를 확인할 수 있다.
  • 이러한 typeid 연산자는 런타임에 객체의 타입을 결정하는 데 사용한다.
  • 또한, 템플릿에서 템플릿 매개변수의 타입을 결정할 때도 사용한다.


typeid(표현식)

References