icon
2장 : 변수와 데이터 타입

기본 데이터 타입


이제부터는 C++ 언어가 데이터를 다루는 방법에 대해 본격적으로 탐구할 시간입니다.

우리가 일상생활에서 다양한 종류의 정보(숫자, 글자, 참/거짓 등)를 사용하듯이, 컴퓨터 프로그램도 숫자, 문자, 논리 값 등 여러 형태의 데이터를 처리해야 합니다.

C++에서는 이러한 데이터의 종류를 구분하기 위해 데이터 타입(Data Type) 이라는 개념을 사용합니다.

이 장에서는 C++이 기본적으로 제공하는 데이터 타입들에 대해 자세히 알아보고, 각 타입이 어떤 종류의 데이터를 저장하며 메모리에서 얼마만큼의 공간을 차지하는지, 그리고 어떤 범위의 값을 표현할 수 있는지 이해하는 데 중점을 둘 것입니다.


데이터 타입이란 무엇인가?

데이터 타입은 프로그램이 데이터를 해석하고 처리하는 방식을 결정하는 속성입니다.

변수를 선언할 때 특정 데이터 타입을 지정하면, 컴파일러는 해당 변수가 어떤 종류의 데이터를 저장할지, 얼마나 많은 메모리 공간을 할당해야 할지, 그리고 그 데이터를 어떻게 연산해야 할지를 알게 됩니다.

예를 들어, 숫자 10을 저장한다고 할 때, 이 10이 정수 10인지, 아니면 10.00과 같은 실수 10인지에 따라 컴퓨터는 내부적으로 다른 방식으로 저장하고 처리합니다.

데이터 타입은 이처럼 데이터의 본질과 그것을 다루는 규칙을 명시하는 역할을 합니다.


정수 타입 (Integer Types)

정수는 소수점 이하가 없는 숫자를 의미합니다.

C++에서는 다양한 크기의 정수 타입을 제공하여, 필요에 따라 효율적으로 메모리를 사용할 수 있도록 합니다.

타입크기 (바이트)값의 범위 (약)설명
char1-128 ~ 127 또는 0 ~ 255단일 문자 또는 작은 정수 값 저장. 문자 인코딩에 사용.
short2-32,768 ~ 32,767작은 정수 값 저장.
int4-2,147,483,648 ~ 2,147,483,647가장 일반적으로 사용되는 정수 타입. 시스템에 따라 크기 변동 가능.
long4 또는 8int와 동일하거나 더 넓은 범위int와 동일하거나 더 큰 정수 값 저장.
long long8-9,223,372,036,854,775,808 ~ 9,223,372,036,854,775,807매우 큰 정수 값 저장.

크기(바이트)와 범위: 위 표의 크기와 범위는 일반적인 시스템에서의 값이며, C++ 표준은 intshort보다 크거나 같고, longint보다 크거나 같고, long longlong보다 크거나 같다고만 명시합니다. 즉, 정확한 크기는 컴파일러와 운영체제, 하드웨어 아키텍처에 따라 달라질 수 있습니다. 하지만 현대 대부분의 시스템에서는 위 표와 같은 크기를 가집니다.

부호 있는 정수와 부호 없는 정수: 위에서 설명한 정수 타입들은 기본적으로 부호 있는(signed) 정수입니다. 즉, 양수와 음수를 모두 표현할 수 있습니다. 만약 음수를 표현할 필요가 없고 오직 양수와 0만을 저장할 것이라면, unsigned 키워드를 붙여 부호 없는(unsigned) 정수 타입을 사용할 수 있습니다.

unsigned 키워드를 붙이면 음수를 표현하는 데 사용되던 비트(bit)를 양수 범위 확장하는 데 사용하므로, 0부터 시작하여 기존 부호 있는 정수보다 두 배 넓은 양수 범위를 가집니다.

  • unsigned char : 0 ~ 255
  • unsigned short : 0 ~ 65,535
  • unsigned int : 0 ~ 4,294,967,295
  • unsigned long : 0 ~ 4,294,967,295 (4바이트 기준) 또는 0 ~ 18,446,744,073,709,551,615 (8바이트 기준)
  • unsigned long long : 0 ~ 18,446,744,073,709,551,615
정수 타입 예시
#include <iostream>
#include <limits> // 각 타입의 최대/최소 값을 확인하기 위해 포함

int main() {
    char singleChar = 'A'; // 단일 문자 저장
    short smallNumber = 100;
    int integerValue = 12345; // 가장 일반적으로 사용
    long bigNumber = 1234567890L; // L 접미사는 long 타입을 명시 (선택적)
    long long veryBigNumber = 9876543210987654321LL; // LL 접미사는 long long 타입을 명시

    unsigned int positiveOnly = 4000000000U; // U 접미사는 unsigned 타입을 명시

    std::cout << "char: " << singleChar << " (크기: " << sizeof(char) << "바이트)" << std::endl;
    std::cout << "short: " << smallNumber << " (크기: " << sizeof(short) << "바이트)" << std::endl;
    std::cout << "int: " << integerValue << " (크기: " << sizeof(int) << "바이트)" << std::endl;
    std::cout << "long: " << bigNumber << " (크기: " << sizeof(long) << "바이트)" << std::endl;
    std::cout << "long long: " << veryBigNumber << " (크기: " << sizeof(long long) << "바이트)" << std::endl;
    std::cout << "unsigned int: " << positiveOnly << " (크기: " << sizeof(unsigned int) << "바이트)" << std::endl;

    // 각 타입의 최대/최소 값 확인 (limits 헤더 필요)
    std::cout << "int 최대값: " << std::numeric_limits<int>::max() << std::endl;
    std::cout << "int 최소값: " << std::numeric_limits<int>::min() << std::endl;
    std::cout << "unsigned int 최대값: " << std::numeric_limits<unsigned int>::max() << std::endl;

    return 0;
}

sizeof 연산자는 특정 데이터 타입이나 변수가 메모리에서 차지하는 바이트 크기를 알려줍니다.

std::numeric_limits<limits> 헤더에 정의된 템플릿 클래스로, 각 숫자 타입의 최소/최대값 등 다양한 정보를 얻을 수 있게 해줍니다.


부동 소수점 타입 (Floating-Point Types)

부동 소수점 타입은 소수점이 있는 숫자(실수)를 저장하는 데 사용됩니다. 정수 타입과 달리, 실수는 컴퓨터 내부에서 약간의 오차를 가질 수 있습니다.

타입크기 (바이트)유효 숫자 자릿수 (약)값의 범위 (약)설명
float46 ~ 7 자리$\pm 3.4 \times 10^-38$ ~ $\pm 3.4 \times 10^38$단정밀도 부동 소수점. 일반적으로 부족.
double815 ~ 17 자리$\pm 1.7 \times 10^-308$ ~ $\pm 1.7 \times 10^308$배정밀도 부동 소수점. 가장 일반적으로 사용.
long double8, 10 또는 1618 ~ 19 자리double보다 크거나 같음더 높은 정밀도와 넓은 범위를 제공.

정밀도: 부동 소수점 타입은 '유효 숫자 자릿수'로 정밀도를 표현합니다. float은 약 67자리의 유효 숫자를, double은 약 1517자리의 유효 숫자를 표현할 수 있습니다. 더 많은 정밀도가 필요하다면 long double을 사용할 수 있습니다. 일반적으로 double이 가장 널리 사용되며, 대부분의 계산에 충분한 정밀도를 제공합니다.

부동 소수점 오차: 컴퓨터는 실수를 이진수로 표현하기 때문에, 0.1과 같은 일부 십진수 실수는 이진수로 정확히 표현할 수 없습니다. 이로 인해 미세한 오차가 발생할 수 있으며, 이는 부동 소수점 연산에서 주의해야 할 부분입니다.

부동 소수점 타입 예시
#include <iostream>
#include <iomanip> // std::fixed, std::setprecision을 사용하기 위해 포함

int main() {
    float pi_float = 3.1415926535F; // F 접미사는 float 타입을 명시
    double pi_double = 3.14159265358979323846; // 기본적으로 double 타입으로 간주
    long double pi_long_double = 3.14159265358979323846L; // L 접미사는 long double 타입을 명시

    std::cout << std::fixed << std::setprecision(20); // 소수점 이하 20자리까지 고정 출력

    std::cout << "float (pi): " << pi_float << " (크기: " << sizeof(float) << "바이트)" << std::endl;
    std::cout << "double (pi): " << pi_double << " (크기: " << sizeof(double) << "바이트)" << std::endl;
    std::cout << "long double (pi): " << pi_long_double << " (크기: " << sizeof(long double) << "바이트)" << std::endl;

    // 부동 소수점 오차 예시
    double result = 0.1 + 0.2;
    std::cout << "0.1 + 0.2 = " << result << std::endl; // 정확히 0.3이 아닐 수 있음

    return 0;
}

std::fixedstd::setprecision<iomanip> 헤더에 정의되어 있으며, 실수를 출력할 때 소수점 이하 자릿수를 제어하는 데 사용됩니다.


문자 타입 (Character Types)

char 타입은 단일 문자를 저장하는 데 사용됩니다.

사실 char는 1바이트 크기의 정수 타입이기도 하며, ASCII 코드와 같은 문자 인코딩 표준에 따라 특정 정수 값이 특정 문자에 매핑됩니다.

  • char: 1바이트. ASCII 문자를 표현하는 데 사용됩니다. (예: 'A', 'a', '1', '@')
  • wchar_t: 2 또는 4바이트. 유니코드(Unicode)와 같이 더 넓은 범위의 문자 집합을 지원하는 데 사용됩니다. 한글과 같은 다국어 문자를 다룰 때 필요합니다.
  • char16_t, char32_t: C++11부터 추가된 유니코드 문자 타입입니다. 각각 16비트와 32비트 유니코드 문자를 표현합니다.
문자 타입 예시
#include <iostream>

int main() {
    char grade = 'A'; // 단일 문자는 작은따옴표로 묶습니다.
    char asciiValue = 65; // ASCII 코드 65는 'A'입니다.

    std::cout << "내 학점: " << grade << std::endl;
    std::cout << "ASCII 값 65는 문자: " << asciiValue << std::endl;

    // wchar_t 예시 (출력을 위해 별도의 설정이 필요할 수 있습니다)
    // wchar_t koreanChar = L'가'; // L 접두사는 wide character를 의미합니다.
    // std::wcout << L"한글 문자: " << koreanChar << std::endl; 

    return 0;
}

논리 타입 (Boolean Type)

논리 타입은 참(true) 또는 거짓(false)이라는 두 가지 값만을 저장합니다.

프로그램의 조건문이나 반복문 등에서 특정 조건의 만족 여부를 판단할 때 사용됩니다.

  • bool: 1바이트. true 또는 false 값을 가집니다.
논리 타입 예시
#include <iostream>

int main() {
    bool isCppFun = true; // 참을 의미하는 true
    bool hasErrors = false; // 거짓을 의미하는 false

    std::cout << "C++은 재밌는가? " << isCppFun << std::endl; // true는 1로, false는 0으로 출력됨
    std::cout << "오류가 있는가? " << hasErrors << std::endl;

    // 논리 연산
    if (isCppFun) {
        std::cout << "아주 재미있습니다!" << std::endl;
    } else {
        std::cout << "더 노력해야겠네요..." << std::endl;
    }

    return 0;
}

bool 타입의 값을 std::cout으로 출력하면 true1로, false0으로 표시됩니다. 만약 truefalse 문자 그대로 출력하고 싶다면 std::boolalpha 조작자를 사용할 수 있습니다.

std::cout << std::boolalpha << "C++은 재밌는가? " << isCppFun << std::endl; // "true"로 출력