본문으로 건너뛰기
안동민 개발노트 아이콘

안동민 개발노트

본문 시작
3장 : 연산자와 표현식

관계 연산자와 논리 연산자

비교식이 만드는 bool 값과 논리 연산의 단락 평가를 이해하고 여러 조건을 정확한 판단식으로 조합합니다.

프로그램은 단순히 계산만 하는 것이 아니라 특정 조건에 따라 다른 동작을 수행해야 할 때가 많습니다.

예를 들어 만약 점수가 60점 이상이면 합격과 같은 조건을 판단해야 합니다.

이때 필요한 것이 바로 관계 연산자(Relational Operators)논리 연산자(Logical Operators)입니다.

이 장에서는 두 값의 크기를 비교하고, 여러 조건을 조합해 참(true)/거짓(false)을 판단하는 방법을 살펴봅니다.

이 연산자들은 앞으로 배우게 될 조건문(if), 반복문(for, while)의 핵심적인 구성 요소가 됩니다.


관계 연산자 (Relational Operators)

관계 연산자와 논리 연산자는 값의 형태, 평가 순서, 경계 입력에서 먼저 확인합니다.

관계 연산자는 두 피연산자 간의 크기 또는 동등성 관계를 비교하여 그 결과로 true (참) 또는 false (거짓)의 bool 타입 값을 반환합니다.

연산자이름설명예시 (결과)
==같다 (Equal to)두 피연산자의 값이 같으면 true, 아니면 false.5 == 5 (true)
!=같지 않다 (Not equal to)두 피연산자의 값이 다르면 true, 아니면 false.5 != 3 (true)
>보다 크다 (Greater than)왼쪽 피연산자가 오른쪽보다 크면 true.5 > 3 (true)
<보다 작다 (Less than)왼쪽 피연산자가 오른쪽보다 작으면 true.5 < 3 (false)
>=보다 크거나 같다 (Greater than or equal to)왼쪽 피연산자가 오른쪽보다 크거나 같으면 true.5 >= 5 (true)
<=보다 작거나 같다 (Less than or equal to)왼쪽 피연산자가 오른쪽보다 작거나 같으면 true.5 <= 3 (false)
주의사항
  • 같다(==)와 대입(=)의 혼동 금지: ==는 비교 연산자이고 =는 대입 연산자입니다. 초보자가 가장 자주 하는 실수 중 하나이므로 항상 주의해야 합니다. if (a = 10)처럼 실수로 대입 연산자를 사용하면 컴파일러 경고가 발생하거나(C++17부터는 특정 상황에서 오류 처리 가능), 의도치 않게 a에 10이 할당되고 조건문이 항상 참이 되는 심각한 버그를 만들 수 있습니다.
  • 실수 비교의 주의: 부동 소수점 수(float, double)는 컴퓨터 내부 표현 방식 때문에 미세한 오차가 발생할 수 있습니다. 따라서 두 실수가 정확히 같은지 ==로 비교하는 것은 위험합니다. 대신, 두 실수의 차이가 아주 작은 값(epsilon)보다 작으면 같다고 간주하는 방식을 사용합니다.
    double a = 0.1 + 0.2; // a는 정확히 0.3이 아닐 수 있음 (예: 0.30000000000000004)
    double b = 0.3;
    if (a == b) { // 대부분 false로 나옴
        std::cout << "a와 b는 같다 (직접 비교)" << std::endl;
    } else {
        std::cout << "a와 b는 다르다 (직접 비교)" << std::endl; // 이 메시지가 출력될 확률이 높음
    }
    const double EPSILON = 0.00000001; // 아주 작은 값 정의
    if (std::abs(a - b) < EPSILON) { // std::abs는 <cmath>에 있음
        std::cout << "a와 b는 거의 같다 (엡실론 비교)" << std::endl; // 이 메시지가 출력
    }
예시
#include <iostream> // std::cout, std::endl 사용
#include <string>   // std::string 사용
#include <cmath>    // std::abs 사용 (실수 비교를 위해)

int main() {
    int score = 75;
    int passingScore = 60;
    std::string name1 = "Alice";
    std::string name2 = "Bob";
    std::string name3 = "Alice";

    // 점수 비교
    bool isPassed = (score >= passingScore);
    std::cout << "합격 여부 (score >= passingScore): " << std::boolalpha << isPassed << std::endl; // true

    bool isPerfect = (score == 100);
    std::cout << "만점 여부 (score == 100): " << std::boolalpha << isPerfect << std::endl;   // false

    // 문자열 비교 (문자열 비교는 기본적으로 사전 순 비교)
    bool namesEqual = (name1 == name2);
    std::cout << "이름 같음 (name1 == name2): " << std::boolalpha << namesEqual << std::endl; // false

    bool namesNotEqual = (name1 != name3);
    std::cout << "이름 같지 않음 (name1 != name3): " << std::boolalpha << namesNotEqual << std::endl; // false

    bool nameOrder = (name1 < name2); // 'A'가 'B'보다 앞서므로 true
    std::cout << "사전순 비교 (name1 < name2): " << std::boolalpha << nameOrder << std::endl; // true

    return 0;
}

논리 연산자 (Logical Operators)

논리 연산자는 bool 타입 피연산자를 사용하여 논리적인 연산(AND, OR, NOT)을 수행하고 그 결과로 true 또는 falsebool 타입 값을 반환합니다.

관계 연산자의 결과(true/false)나 다른 bool 변수를 조합하여 더 복잡한 조건을 만들 때 사용됩니다.

연산자이름설명예시 (결과)
&&논리 AND (Logical AND)두 피연산자 모두 true일 때만 true, 아니면 false.(true && false) (false)
||논리 OR (Logical OR)두 피연산자 중 하나라도 true이면 true, 모두 false일 때만 false.(true || false) (true)
!논리 NOT (Logical NOT)피연산자의 논리 값을 반전시킵니다. (truefalse로, falsetrue로).!true (false)

논리 AND(&&): 두 조건이 모두 참일 때만 전체 결과가 참이 됩니다.

A && B

  • A가 true이고 B가 true일 때 -> true
  • A가 true이고 B가 false일 때 -> false
  • A가 false이고 B가 true일 때 -> false
  • A가 false이고 B가 false일 때 -> false

논리 OR(||): 두 조건 중 하나라도 참일 때 전체 결과가 참이 됩니다. A || B

  • A가 true이고 B가 true일 때 -> true
  • A가 true이고 B가 false일 때 -> true
  • A가 false이고 B가 true일 때 -> true
  • A가 false이고 B가 false일 때 -> false

논리 NOT(!): 단항 연산자로, 피연산자의 논리 값을 반전시킵니다.

!A

  • A가 true일 때 -> false
  • A가 false일 때 -> true

단락 평가 (Short-Circuit Evaluation): &&|| 연산자는 단락 평가라는 특징을 가집니다.

이는 연산의 결과를 결정하기 위해 모든 피연산자를 평가할 필요가 없을 때, 더 이상 평가를 진행하지 않는다는 의미입니다.

  • A && B: 만약 Afalse라면, B의 값에 관계없이 전체 표현식은 false가 됩니다. 따라서 B는 평가되지 않습니다.
  • A || B: 만약 Atrue라면, B의 값에 관계없이 전체 표현식은 true가 됩니다. 따라서 B는 평가되지 않습니다.

이러한 단락 평가는 특정 조건이 만족될 때만 안전하게 다음 코드를 실행해야 하는 경우에 유용합니다.

예를 들어 포인터가 유효한지 먼저 확인한 후, 그 포인터를 사용하는 코드를 실행할 때 활용됩니다.

아래 다이어그램은 비교식이 bool 값이 되고, 논리 연산자로 조합된 뒤 단락 평가를 거쳐 조건문에서 사용되는 흐름을 보여줍니다.

단락 평가 예시
// if (ptr != nullptr && ptr->member == value) { ... }
// 만약 ptr이 nullptr이면, ptr != nullptr이 false가 되어 ptr->member에 접근하지 않아 안전함.
논리 연산자 예시
#include <iostream>

int main() {
    int age = 20;
    bool hasLicense = true;
    bool hasCar = false;
    int points = 85;

    // 성인이고 면허가 있는지 (AND)
    bool canDrive = (age >= 18) && hasLicense;
    std::cout << "운전 가능 (성인 && 면허): " << std::boolalpha << canDrive << std::endl; // true

    // 면허가 있거나 차가 있는지 (OR)
    bool needsTransport = hasLicense || hasCar;
    std::cout << "교통수단 필요 (면허 || 차): " << std::boolalpha << needsTransport << std::endl; // true (면허가 있으므로)

    // 시험에 불합격했는지 (NOT)
    bool isFailed = !(points >= 70); // 70점 이상이면 합격이므로, 그 반대는 불합격
    std::cout << "시험 불합격 (만점 여부): " << std::boolalpha << isFailed << std::endl; // false (85점은 합격)

    // 복합 조건
    bool canRentCar = (age >= 21) && hasLicense && (points >= 80);
    std::cout << "렌터카 가능 (복합 조건): " << std::boolalpha << canRentCar << std::endl; // false (age >= 21이 false)

    return 0;
}

C++ 연산자 우선순위와 결합 규칙

복잡한 표현식에서는 산술 연산자, 관계 연산자, 논리 연산자가 함께 사용될 수 있습니다.

이때 어떤 연산이 먼저 수행될지 이해하는 것이 중요합니다.

일반적인 우선순위는 다음과 같습니다 (높은 것에서 낮은 것 순)

단항 연산자 (!, ++, --, +, -)

산술 연산자 (*, /, % 다음 +, -)

관계 연산자 (<, >, <=, >=)

관계 연산자 (==, !=)

논리 AND (&&)

논리 OR (||)

대입 연산자 (=, +=, -= 등)

예시
int x = 10, y = 5, z = 15;
bool result = x + y > z && z - y < x;
// 1. 산술 연산 먼저:
//    x + y  -> 10 + 5 = 15
//    z - y  -> 15 - 5 = 10
// 2. 관계 연산 다음:
//    15 > z -> 15 > 15 -> false
//    10 < x -> 10 < 10 -> false
// 3. 논리 AND 연산 마지막:
//    false && false -> false
std::cout << "복합 조건 결과: " << std::boolalpha << result << std::endl; // 출력: false

이처럼 괄호를 적절히 사용하여 연산 순서를 명확히 하는 것이 코드의 가독성을 높이는 데 매우 중요합니다.

아래 다이어그램은 비교식과 논리 연산자를 조합할 때 실수 비교, 단락 평가, 괄호 기준을 함께 점검하는 조건식 작성 흐름입니다.

아래 다이어그램은 조건식에서 자주 나오는 실수를 안전한 bool 표현으로 고치는 기준을 정리합니다.