icon
3장 : 연산자와 표현식

기타 연산자

프로그램에서 변수의 값을 변경하고, 특정 조건에 따라 간결하게 값을 결정하며, 메모리나 타입 정보를 얻는 등 다양한 상황에서 유용하게 사용되는 기타 연산자들에 대해 알아보겠습니다.

이 장에서는 대입 연산자, 복합 대입 연산자, 조건(삼항) 연산자, 크기 연산자(sizeof), 주소 연산자(&), 간접 참조 연산자(*), 그리고 콤마 연산자(,) 등 다양한 연산자들의 기능과 사용법을 상세히 살펴보겠습니다.


대입 연산자 (=)

대입 연산자(=) 는 오른쪽 피연산자의 값을 왼쪽 피연산자(변수)에 할당합니다.

가장 기본적인 연산자 중 하나이며, 변수의 값을 변경하거나 초기화할 때 사용됩니다.

대입 연산자 예시
int age = 20; // 20을 age 변수에 대입 (초기화)
age = 21;     // 21을 age 변수에 대입 (값 변경)

double pi = 3.14;
char grade = 'A';

대입 연산은 오른쪽에서 왼쪽으로 진행됩니다.

대입 연산의 결과는 대입된 값 자체입니다.

이를 활용하여 여러 변수에 동시에 같은 값을 대입할 수 있습니다.

동시 대입 예시
int x, y, z;
x = y = z = 10; // z에 10 대입, y에 z의 값(10) 대입, x에 y의 값(10) 대입
std::cout << "x: " << x << ", y: " << y << ", z: " << z << std::endl; // 출력: x: 10, y: 10, z: 10

복합 대입 연산자

복합 대입 연산자는 산술 연산, 비트 연산 등과 대입 연산을 결합한 형태입니다.

변수 = 변수 연산 값 형태의 코드를 변수 연산= 값 형태로 간결하게 줄여줍니다.

이는 코드의 가독성을 높이고, 컴파일러가 최적화를 수행하는 데 도움을 줄 수 있습니다.

연산자예시의미
+=a += b;a = a + b;
-=a -= b;a = a - b;
*=a *= b;a = a * b;
/=a /= b;a = a / b;
%=a %= b;a = a % b;
&=a &= b;a = a & b;
|=a |= b;a = a | b;
^=a ^= b;a = a ^ b;
<<=a <<= b;a = a << b;
>>=a >>= b;a = a >> b;
복합 대입 연산자 예시
#include <iostream>

int main() {
    int score = 100;
    score += 50; // score = score + 50;  -> score는 150
    std::cout << "score: " << score << std::endl;

    double price = 100.0;
    price *= 0.8; // price = price * 0.8; -> price는 80.0
    std::cout << "price: " << price << std::endl;

    int flags = 0b0010; // 십진수 2
    flags |= 0b0100;    // flags = flags | 0b0100; -> flags는 0b0110 (십진수 6)
    std::cout << "flags: " << flags << std::endl;

    return 0;
}

조건(삼항) 연산자 (? :)

조건 연산자(Conditional Operator) 는 유일한 삼항(ternary) 연산자로, 세 개의 피연산자를 가집니다.

특정 조건에 따라 두 값 중 하나를 선택하는 데 사용됩니다. if-else 문을 간결하게 한 줄로 표현할 때 유용합니다.

조건 연산자 형식
조건 ? 표현식1 : 표현식2;
  • 조건true이면 표현식1이 평가되고 그 결과가 반환됩니다.
  • 조건false이면 표현식2가 평가되고 그 결과가 반환됩니다.
조건 연산자 예시
#include <iostream>
#include <string>

int main() {
    int age = 19;
    std::string status = (age >= 18) ? "성인" : "미성년자";
    std::cout << "당신은 " << status << "입니다." << std::endl; // 출력: 당신은 성인입니다.

    int num1 = 10;
    int num2 = 20;
    int max_val = (num1 > num2) ? num1 : num2;
    std::cout << "두 수 중 큰 값: " << max_val << std::endl; // 출력: 20

    // 조건 연산자의 결과를 변수에 할당하지 않고 바로 사용할 수도 있습니다.
    std::cout << "시험 결과: " << (85 >= 60 ? "합격" : "불합격") << std::endl; // 출력: 합격

    return 0;
}

조건 연산자는 간결하지만 너무 복잡한 조건이나 표현식을 사용하면 가독성이 떨어질 수 있으므로 적절히 사용하는 것이 중요합니다.


크기 연산자 (sizeof)

sizeof 연산자는 특정 데이터 타입 또는 변수가 메모리에서 차지하는 바이트(byte) 크기를 반환합니다.

컴파일 시점에 결정되며, 주로 메모리 관리가 중요한 시스템 프로그래밍이나 데이터 구조의 크기를 파악할 때 사용됩니다.

sizeof 연산자 형식
sizeof(타입_이름);
sizeof(변수_이름);

괄호를 생략할 수도 있지만, 타입을 인자로 사용할 때는 필수로 붙여야 합니다.

sizeof 연산자 예시
#include <iostream>

int main() {
    int myInt;
    double myDouble;
    char myChar;
    bool myBool;

    std::cout << "int의 크기: " << sizeof(int) << " 바이트" << std::endl;
    std::cout << "myInt 변수의 크기: " << sizeof(myInt) << " 바이트" << std::endl;
    std::cout << "double의 크기: " << sizeof(double) << " 바이트" << std::endl;
    std::cout << "myDouble 변수의 크기: " << sizeof(myDouble) << " 바이트" << std::endl;
    std::cout << "char의 크기: " << sizeof(char) << " 바이트" << std::endl;
    std::cout << "myChar 변수의 크기: " << sizeof(myChar) << " 바이트" << std::endl;
    std::cout << "bool의 크기: " << sizeof(bool) << " 바이트" << std::endl;
    std::cout << "myBool 변수의 크기: " << sizeof(myBool) << " 바이트" << std::endl;

    // 배열의 크기
    int numbers[5];
    std::cout << "numbers 배열의 전체 크기: " << sizeof(numbers) << " 바이트" << std::endl; // 5 * sizeof(int)
    std::cout << "numbers 배열의 요소 개수: " << sizeof(numbers) / sizeof(numbers[0]) << std::endl; // 배열 길이 계산

    return 0;
}

sizeof는 배열의 전체 크기를 구할 때 매우 유용하며, 이를 통해 배열의 요소 개수를 안전하게 계산할 수 있습니다.


주소 연산자 (&)

주소 연산자(&, Address-of Operator) 는 변수의 메모리 주소를 반환합니다.

이 연산자는 포인터(Pointer) 와 함께 사용됩니다.

포인터는 변수의 메모리 주소를 저장하는 특별한 타입의 변수입니다.

포인터에 대한 자세한 내용은 나중에 별도로 다시 다룰 것입니다.

주소 연산자 형식
&변수_이름;
주소 연산자 예시
#include <iostream>

int main() {
    int value = 123;
    double pi = 3.14;

    std::cout << "value 변수의 값: " << value << std::endl;
    std::cout << "value 변수의 메모리 주소: " << &value << std::endl; // 16진수 주소 출력

    std::cout << "pi 변수의 값: " << pi << std::endl;
    std::cout << "pi 변수의 메모리 주소: " << &pi << std::endl;

    return 0;
}

출력되는 메모리 주소는 실행할 때마다 달라질 수 있으며, 16진수 형태로 표시됩니다.


간접 참조 연산자 (*)

간접 참조 연산자(*, Dereference Operator / Indirection Operator) 는 포인터 변수가 가리키는 메모리 주소에 저장된 실제 값에 접근할 때 사용됩니다.

역시 포인터 개념과 밀접하게 연관됩니다.

간접 참조 연산자 형식
*포인터_변수;
간접 참조 연산자 예시
#include <iostream>

int main() {
    int data = 100;
    int* ptr = &data; // ptr은 data의 메모리 주소를 저장하는 포인터 변수

    std::cout << "data의 값: " << data << std::endl;         // 출력: 100
    std::cout << "ptr에 저장된 주소: " << ptr << std::endl;  // data의 주소 출력
    std::cout << "ptr이 가리키는 값: " << *ptr << std::endl; // 출력: 100 (*ptr은 data와 동일)

    *ptr = 200; // ptr이 가리키는 메모리(즉, data)의 값을 200으로 변경
    std::cout << "data의 새로운 값: " << data << std::endl; // 출력: 200

    return 0;
}

* 기호는 포인터 변수를 선언할 때(int* ptr;)는 '포인터 타입'임을 나타내고, 포인터 변수 앞에 사용될 때는 '간접 참조'를 나타내므로 혼동하지 않도록 주의해야 합니다.


콤마 연산자 (,)

콤마 연산자(Comma Operator) 는 두 개 이상의 표현식을 순차적으로 평가하고, 가장 마지막 표현식의 결과를 반환합니다. 주로 for 반복문 헤더에서 여러 초기화나 증감식을 한 줄에 작성할 때 사용됩니다.

콤마 연산자 형식
표현식1, 표현식2, 표현식3, ... , 마지막_표현식;
콤마 연산자 예시
#include <iostream>

int main() {
    int x = 10, y = 20; // 변수 선언 시 콤마 사용 (연산자 아님)

    // 콤마 연산자 사용 (표현식)
    int result = (x++, y += 5, x + y); // 1. x를 11로 증가, 2. y를 25로 증가, 3. (11 + 25) 계산
                                      // 최종적으로 (x + y)의 결과인 36이 result에 대입
    std::cout << "x: " << x << ", y: " << y << ", result: " << result << std::endl; // 출력: x: 11, y: 25, result: 36

    // for 문에서 활용
    for (int i = 0, j = 10; i < 5; ++i, --j) {
        std::cout << "i: " << i << ", j: " << j << std::endl;
    }
    /* 출력:
    i: 0, j: 10
    i: 1, j: 9
    i: 2, j: 8
    i: 3, j: 7
    i: 4, j: 6
    */
    return 0;
}

콤마 연산자는 매우 낮은 우선순위를 가지므로, 다른 연산자와 함께 사용할 때는 괄호로 명확히 하는 것이 좋습니다.