[2026] C++ 변수와 자료형 | int, double, string 완벽 정리 [초보자용]
이 글의 핵심
C++ 변수와 자료형: int, double, string [초보자용]. C++ 기본 자료형 한눈에 보기·자료형 심화.
C++ 기본 자료형 한눈에 보기
| 자료형 | 크기 | 범위 | 용도 |
|---|---|---|---|
| int | 4바이트 | -2^31 ~ 2^31-1 | 정수 |
| long long | 8바이트 | -2^63 ~ 2^63-1 | 큰 정수 |
| float | 4바이트 | 약 ±3.4e38 | 실수 (정밀도 낮음) |
| double | 8바이트 | 약 ±1.7e308 | 실수 (정밀도 높음) |
| char | 1바이트 | -128 ~ 127 | 문자 |
| bool | 1바이트 | true/false | 논리값 |
| string | 가변 | - | 문자열 (STL) |
자료형 심화
정수형 크기: int, long, long long
C++에서 정수형의 정확한 바이트 수는 구현과 플랫폼에 따라 달라질 수 있습니다. 실무에서는 <cstdint>의 고정 크기 타입(int32_t, int64_t 등)을 쓰기도 하지만, 초보 단계에서는 표준 정수형의 관계만 이해하면 됩니다.
- int: 대부분의 환경에서 4바이트(32비트). 일상적인 정수 연산의 기본 선택입니다.
- long: Windows MSVC에서는
int와 같이 4바이트인 경우가 많고, Linux 64비트에서는long이 8바이트인 경우도 있습니다. 이식성이 필요하면long에 의존하지 말고 범위가 크면long long을 쓰는 편이 안전합니다. - long long: 최소 64비트 이상이 보장됩니다. 큰 수, 오버플로우를 피해야 하는 누적 합, 파일 크기 등에 적합합니다. 아래 코드는 cpp를 사용한 구현 예제입니다. 필요한 모듈을 import하고. 코드를 직접 실행해보면서 동작을 확인해보세요.
#include <iostream>
int main() {
int a = 2147483647; // int 최댓값 근처
long long b = 2147483648LL; // int를 넘는 값은 LL 접미사 권장
std::cout << a << ", " << b << "\n";
return 0;
}
요약: int로 충분한지 먼저 보고, 범위가 부족하면 long long으로 올리세요. long은 플랫폼별 차이를 기억해 두세요.
부호 있는 타입과 없는 타입 (signed, unsigned)
- signed: 기본적으로
int,short등은 부호가 있습니다(음수·양수).signed int와int는 같은 의미입니다. - unsigned: 음수를 표현하지 않고 0 이상만 표현합니다. 같은 비트 폭이면 양의 범위가 약 두 배 넓어집니다.
unsigned int u = 4000000000U; // int로는 못 담을 수 있는 큰 양수
unsigned char flags = 255; // 0~255
주의: unsigned와 int를 섞어 연산하면 보통 unsigned 쪽으로 승격되어, 음수가 있던 변수가 거대한 양수로 해석되는 버그가 납니다. 비교·뺄셈 전에 타입을 맞추거나 static_cast로 의도를 명확히 하세요.
int x = -1;
unsigned int y = 10;
if (x < y) { } // 기대와 다르게 동작할 수 있음 (-1이 unsigned로 변환되면 큰 양수)
실수형 정밀도: float vs double
| 구분 | float | double |
|---|---|---|
| 대략적인 유효 숫자 | 6~7자리 | 15~16자리 |
| 용도 | 메모리 절약, GPU 등 | 일반 계산의 기본 |
일반 애플리케이션에서는 double을 기본으로 쓰는 것이 좋습니다. 3.14 같은 리터럴도 C++에서는 기본적으로 double입니다. float 리터럴은 접미사 f를 붙입니다 (3.14f). |
float f = 3.14f;
double d = 3.14; // double
auto x = 3.14; // 역시 double
char vs string
- char: 문자 하나를 담습니다(ASCII 한 글자 등). 작은따옴표
'A'를 사용합니다. - std::string: 문자열(여러 글자). 큰따옴표
"hello"를 사용합니다. 아래 코드는 cpp를 사용한 구현 예제입니다. 필요한 모듈을 import하고. 코드를 직접 실행해보면서 동작을 확인해보세요.
#include <string>
char letter = 'A'; // 한 글자
std::string name = "Hong"; // 문자열
// char wrong = "Hello"; // 오류: 문자열을 char에 넣을 수 없음
한글처럼 멀티바이트 문자는 한 char에 다 들어가지 않을 수 있습니다. 입문 단계에서는 ASCII와 std::string 위주로 이해하고, 유니코드가 필요하면 이후에 std::u8string 등을 별도로 학습하면 됩니다.
변수 선언과 초기화
선언만 하기 vs 초기화하기
- 선언만: 변수의 이름과 타입만 정하고, 값은 아직 넣지 않습니다. 지역 변수는 읽기 전에 초기화하지 않으면 쓰레기 값이 들어갈 수 있습니다.
- 초기화: 선언과 동시에(또는 그 직후) 첫 값을 넣습니다. 가능하면 선언과 동시에 초기화하는 습관이 안전합니다. 아래 코드는 cpp를 사용한 구현 예제입니다. 코드를 직접 실행해보면서 동작을 확인해보세요.
int score = 100; // 선언 + 초기화 (권장)
double pi = 3.14159;
char grade = 'A';
bool passed = true;
std::string user = "홍길동";
기본 선언 예제
다음은 cpp를 활용한 상세한 구현 코드입니다. 필요한 모듈을 import하고. 각 부분의 역할을 이해하면서 코드를 살펴보시기 바랍니다.
#include <iostream>
#include <string>
int main() {
// 선언만 (지역 변수는 초기화 전 사용 금지)
int age;
// 선언과 동시에 초기화 (권장)
int score = 100;
double pi = 3.14159;
char grade = 'A';
bool isPassed = true;
std::string name = "홍길동";
age = 20; // 나중에 대입
return 0;
}
중괄호 초기화 {} (Uniform initialization)
C++11 이후에는 중괄호 초기화를 많이 씁니다. 좁은 변환(narrowing)이 잡혀 실수를 줄여 줍니다. 아래 코드는 cpp를 사용한 구현 예제입니다. 코드를 직접 실행해보면서 동작을 확인해보세요.
int a{42};
double b{3.14};
int c = {7}; // 동일한 의미
// int x{3.14}; // 일부 컴파일러에서 narrowing 에러 — 의도하지 않은 실수→정수 방지
{} 초기화는 벡터 등 컨테이너 초기화와도 문법이 통일되어 읽기 좋습니다.
auto 키워드
오른쪽 표현식의 타입을 컴파일러가 추론합니다. 타입이 길거나 복잡할 때 유용합니다.
auto x = 10; // int
auto y = 3.14; // double
auto name = std::string("Kim"); // std::string
auto z = "text";는 const char*로 잡힐 수 있어, std::string이 필요하면 명시적으로 std::string을 쓰는 편이 낫습니다.
const와 constexpr
- const: 실행 중에 바꿀 수 없는 읽기 전용 값입니다. 런타임에 결정되는 값으로 초기화할 수 있습니다.
const int MAX = 100;
const double PI = 3.14159;
// MAX = 200; // 오류
- constexpr: 컴파일 타임에 값이 확정되는 상수에 사용합니다. 배열 크기 등에 쓰면 성능·명확성에 유리합니다. 아래 코드는 cpp를 사용한 구현 예제입니다. 코드를 직접 실행해보면서 동작을 확인해보세요.
constexpr int buf_size = 1024;
int arr[buf_size]; // C++에서 constexpr 크기 허용
constexpr int square(int x) { return x * x; }
constexpr int nine = square(3);
입문 단계에서는 const로 “변하지 않는 변수”를 표현하고, 컴파일 상수가 필요할 때 constexpr을 추가로 학습하면 됩니다.
여러 변수 한 번에 선언
아래 코드는 cpp를 사용한 구현 예제입니다. 코드를 직접 실행해보면서 동작을 확인해보세요.
// 같은 타입 여러 개
int a = 1, b = 2, c = 3;
// 권장: 한 줄에 하나씩 (가독성·디버깅)
int a = 1;
int b = 2;
int c = 3;
타입 변환
암시적 변환 (자동)
연산자나 대입 시 컴파일러가 타입을 맞추기 위해 자동으로 변환합니다. 아래 코드는 cpp를 사용한 구현 예제입니다. 코드를 직접 실행해보면서 동작을 확인해보세요.
int i = 10;
double d = i; // int → double (대체로 안전)
double x = 9.99;
int j = x; // 소수 부분 버림 (9). 의도한 경우에만 사용
int a = 5, b = 2;
double r = a / b; // 정수 나눗셈 먼저 → 2.0 (암시적 변환의 함정)
작은 타입이 큰 타입으로 갈 때는 정보 손실이 적고, 큰 타입을 작은 타입으로 넣을 때는 잘림·오버플로우에 주의하세요.
명시적 캐스팅: static_cast
C 스타일 (double)a 대신 static_cast를 쓰면 검색이 쉽고 의도가 분명합니다.
double r1 = static_cast<double>(5) / 2; // 2.5
int rounded = static_cast<int>(3.99); // 3
포인터 간 변환 등은 다른 종류의 캐스트(reinterpret_cast 등)가 필요할 수 있지만, 변수와 기본 타입 사이에서는 static_cast가 기본입니다.
형 변환 주의사항
- 부호 있는 정수 ↔ unsigned: 부호 없는 쪽으로 맞추면 음수가 큰 양수로 바뀝니다.
- 큰 정수 → 작은 정수: 상위 비트가 잘려 값이 달라집니다.
- 실수 → 정수: 소수는 버려지며, 범위를 넘으면 정의되지 않은 동작이 될 수 있습니다.
- 정수 나눗셈: 피연산자가 모두 정수면 결과도 정수입니다. 실수 나눗셈이 필요하면 한쪽을
double로 바꾸세요.
실전 예제
예제 1: 계산기 프로그램 (0으로 나누기 방지)
#include <iostream>
int main() {
double num1 = 0, num2 = 0;
char op = 0;
std::cout << "첫 번째 숫자: ";
if (!(std::cin >> num1)) {
std::cerr << "숫자가 아닙니다.\n";
return 1;
}
std::cout << "연산자 (+, -, *, /): ";
std::cin >> op;
std::cout << "두 번째 숫자: ";
if (!(std::cin >> num2)) {
std::cerr << "숫자가 아닙니다.\n";
return 1;
}
double result = 0;
bool ok = true;
if (op == '+') result = num1 + num2;
else if (op == '-') result = num1 - num2;
else if (op == '*') result = num1 * num2;
else if (op == '/') {
if (num2 == 0.0) {
std::cerr << "0으로 나눌 수 없습니다.\n";
return 1;
}
result = num1 / num2;
} else {
std::cerr << "지원하지 않는 연산자입니다.\n";
ok = false;
}
if (ok) std::cout << "결과: " << result << std::endl;
return 0;
}
double로 읽어 정수 나눗셈 실수를 피하고, 나눗셈 전에 0 여부를 검사했습니다.
예제 2: 온도 변환기 (섭씨 ↔ 화씨)
다음은 cpp를 활용한 상세한 구현 코드입니다. 필요한 모듈을 import하고. 각 부분의 역할을 이해하면서 코드를 살펴보시기 바랍니다.
#include <iostream>
int main() {
double celsius = 0;
std::cout << "섭씨 온도: ";
std::cin >> celsius;
double fahrenheit = celsius * 9.0 / 5.0 + 32;
std::cout << celsius << "°C = " << fahrenheit << "°F\n";
// 화씨 → 섭씨: C = (F - 32) * 5/9
double back = (fahrenheit - 32.0) * 5.0 / 9.0;
std::cout << "역변환 확인: " << back << "°C\n";
return 0;
}
9.0 / 5.0처럼 실수 리터럴을 써서 정수 나눗셈(9/5 == 1)이 되지 않게 했습니다.
예제 3: 입력 검증 (범위·타입)
다음은 cpp를 활용한 상세한 구현 코드입니다. 필요한 모듈을 import하고, 조건문으로 분기 처리를 수행합니다. 각 부분의 역할을 이해하면서 코드를 살펴보시기 바랍니다.
#include <iostream>
#include <limits>
int main() {
int age = 0;
std::cout << "나이 (1~150): ";
if (!(std::cin >> age)) {
std::cerr << "숫자를 입력하세요.\n";
std::cin.clear();
std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
return 1;
}
if (age < 1 || age > 150) {
std::cerr << "범위를 벗어났습니다.\n";
return 1;
}
std::cout << "입력한 나이: " << age << std::endl;
return 0;
}
std::cin 실패 시 clear와 ignore로 버퍼를 비우지 않으면 다음 입력이 꼬일 수 있어, 반복 입력 루프를 만들 때 특히 중요합니다.
예제 4: BMI 계산기
다음은 cpp를 활용한 상세한 구현 코드입니다. 필요한 모듈을 import하고, 조건문으로 분기 처리를 수행합니다. 각 부분의 역할을 이해하면서 코드를 살펴보시기 바랍니다.
#include <iostream>
#include <iomanip> // setprecision
int main() {
double height = 0, weight = 0;
std::cout << "키(cm): ";
std::cin >> height;
std::cout << "몸무게(kg): ";
std::cin >> weight;
double heightM = height / 100.0;
double bmi = weight / (heightM * heightM);
std::cout << std::fixed << std::setprecision(1);
std::cout << "BMI: " << bmi << std::endl;
if (bmi < 18.5) std::cout << "저체중" << std::endl;
else if (bmi < 23) std::cout << "정상" << std::endl;
else if (bmi < 25) std::cout << "과체중" << std::endl;
else std::cout << "비만" << std::endl;
return 0;
}
키를 미터로 바꿀 때 100.0으로 나누어 실수 나눗셈이 되도록 했습니다.
흔한 실수
1. 초기화하지 않은 변수 사용
지역 변수는 자동으로 0이 되지 않습니다. 읽기 전에 반드시 값을 넣으세요. 아래 코드는 cpp를 사용한 구현 예제입니다. 코드를 직접 실행해보면서 동작을 확인해보세요.
// ❌ 위험
int x;
std::cout << x;
// ✅ 안전
int x = 0;
2. 정수 나눗셈 (5 / 2 == 2)
int끼리 나누면 몫만 나옵니다. 평균·비율에는 double이나 static_cast를 사용하세요.
int a = 5, b = 2;
double wrong = a / b; // 2.0
double right = static_cast<double>(a) / b; // 2.5
3. 오버플로우
int 최댓값을 넘기면 정의된 범위에서 래핑되어 음수가 될 수 있습니다.
아래 코드는 cpp를 사용한 구현 예제입니다. 코드를 직접 실행해보면서 동작을 확인해보세요.
int max = 2147483647;
std::cout << max + 1 << "\n"; // -2147483648 (일반적인 2의 보수 환경)
long long big = 2147483647LL;
std::cout << big + 1 << "\n"; // 2147483648
큰 합·곱이 예상되면 처음부터 long long을 쓰거나 범위를 검사하세요.
4. 타입 불일치 (특히 unsigned와 혼합)
unsigned와 int를 비교하면 암시적 변환으로 논리 오류가 날 수 있습니다. 혼합 연산 전에 타입을 통일하거나 static_cast로 의도를 드러내세요.
5. char와 string 혼동
아래 코드는 cpp를 사용한 구현 예제입니다. 코드를 직접 실행해보면서 동작을 확인해보세요.
// ❌ 컴파일 에러
// char name = "Hong";
// ✅
char initial = 'H';
std::string name = "Hong";
자주 하는 실수 (요약 예제)
실수 1: 초기화하지 않은 변수 사용
아래 코드는 cpp를 사용한 구현 예제입니다. 코드를 직접 실행해보면서 동작을 확인해보세요.
// ❌ 위험한 코드
int x;
std::cout << x; // 쓰레기 값 출력
// ✅ 올바른 코드
int x = 0;
std::cout << x; // 0 출력
실수 2: 정수 나눗셈
아래 코드는 cpp를 사용한 구현 예제입니다. 코드를 직접 실행해보면서 동작을 확인해보세요.
// ❌ 예상과 다른 결과
int a = 5, b = 2;
double result = a / b; // 2.0 (정수 나눗셈)
// ✅ 올바른 코드
double result = static_cast<double>(a) / b; // 2.5
// 또는
double result = a / static_cast<double>(b); // 2.5
실수 3: char vs string
아래 코드는 cpp를 사용한 구현 예제입니다. 코드를 직접 실행해보면서 동작을 확인해보세요.
// ❌ 컴파일 에러
// char name = "Hong"; // char는 한 글자만
// ✅ 올바른 코드
char initial = 'H';
std::string name = "Hong";
형변환 (Type Casting) — 빠른 참고
암시적 형변환 (자동)
아래 코드는 cpp를 사용한 구현 예제입니다. 코드를 직접 실행해보면서 동작을 확인해보세요.
int i = 10;
double d = i; // int → double (안전)
double d2 = 3.14;
int i2 = d2; // double → int (소수점 버림, 주의!)
명시적 형변환 (수동)
아래 코드는 cpp를 사용한 구현 예제입니다. 코드를 직접 실행해보면서 동작을 확인해보세요.
// C 스타일 (가능하면 피하기)
double d = (double)5 / 2;
// C++ 스타일 (권장)
double d = static_cast<double>(5) / 2;
추가 자료형
unsigned (부호 없는 정수)
unsigned int age = 25; // 0 ~ 4,294,967,295
unsigned long long big = 18446744073709551615ULL; // 매우 큰 수
사용 시기: 음수가 절대 없는 경우 (나이, 개수 등). 단, unsigned와 signed를 섞지 않도록 주의하세요.
auto (자동 타입 추론) - C++11
auto x = 10; // int로 추론
auto y = 3.14; // double로 추론
auto str = std::string("Hong"); // std::string
장점: 타입이 복잡할 때 편리합니다.
단점: auto만 보고 타입이 안 보일 수 있으니, 팀 규칙에 맞게 사용하세요.
const (상수)
아래 코드는 cpp를 사용한 구현 예제입니다. 코드를 직접 실행해보면서 동작을 확인해보세요.
const int MAX_SCORE = 100; // 변경 불가
// MAX_SCORE = 200; // 컴파일 에러!
const double PI = 3.14159;
const std::string COMPANY = "ABC Corp";
FAQ
Q1: int와 long의 차이는 무엇인가요?
A: 크기가 다릅니다.
| 타입 | 크기 | 범위 |
|---|---|---|
| int | 4바이트 | -2,147,483,648 ~ 2,147,483,647 |
| long | 4바이트 (Windows) / 8바이트 (Linux) | 플랫폼 의존적 |
| long long | 8바이트 | -9,223,372,036,854,775,808 ~ 9,223,372,036,854,775,807 |
권장: 큰 수가 필요하면 long long 사용 (플랫폼 독립적) |
Q2: float와 double 중 무엇을 써야 하나요?
A: 대부분 double을 사용하세요.
이유:
float: 정밀도 낮음 (소수점 6-7자리)double: 정밀도 높음 (소수점 15-16자리)- 성능 차이: 거의 없음 (현대 CPU) float 사용 시기:
- 메모리가 매우 제한적인 경우
- GPU 프로그래밍
- 대량의 실수 배열
Q3: string은 왜 std::를 붙여야 하나요?
A: string은 C++ 표준 라이브러리(STL)의 클래스이기 때문입니다.
아래 코드는 cpp를 사용한 구현 예제입니다. 필요한 모듈을 import하고. 각 부분의 역할을 이해하면서 코드를 살펴보시기 바랍니다.
#include <string>
// 방법 1: std:: 붙이기
std::string name = "Hong";
// 방법 2: using 선언
using std::string;
string name = "Hong";
// 방법 3: using namespace (비추천)
using namespace std;
string name = "Hong";
Q4: 변수 이름 규칙은 무엇인가요?
A: 다음 규칙을 따르세요. 가능:
- 영문자, 숫자, 언더스코어(_)
- 영문자나 언더스코어로 시작
- 대소문자 구분 아래 코드는 cpp를 사용한 구현 예제입니다. 각 부분의 역할을 이해하면서 코드를 살펴보시기 바랍니다.
// ✅ 올바른 이름
int age;
int user_count;
int maxScore;
int _temp;
// ❌ 잘못된 이름
int 2age; // 숫자로 시작 불가
int user-count; // 하이픈 불가
int max score; // 공백 불가
네이밍 컨벤션 (권장): 아래 코드는 cpp를 사용한 구현 예제입니다. 조건문으로 분기 처리를 수행합니다. 각 부분의 역할을 이해하면서 코드를 살펴보시기 바랍니다.
// camelCase (일반 변수)
int userAge = 25;
int maxScore = 100;
// snake_case (일부 프로젝트)
int user_age = 25;
int max_score = 100;
// UPPER_CASE (상수)
const int MAX_USERS = 1000;
const double PI = 3.14159;
Q5: 왜 초기화를 해야 하나요?
A: 초기화하지 않으면 “쓰레기 값”이 들어갑니다. 아래 코드는 cpp를 사용한 구현 예제입니다. 필요한 모듈을 import하고, 조건문으로 분기 처리를 수행합니다. 각 부분의 역할을 이해하면서 코드를 살펴보시기 바랍니다.
#include <iostream>
int main() {
int x; // 초기화 안 함
std::cout << x; // 쓰레기 값 출력 (예: 32767, -1, 0 등 랜덤)
if (x > 100) { // 예상 못한 동작
}
return 0;
}
해결법: 항상 초기화하세요.
int x = 0; // 안전
Q6: 오버플로우는 무엇인가요?
A: 자료형의 범위를 넘어서는 경우입니다. 아래 코드는 cpp를 사용한 구현 예제입니다. 필요한 모듈을 import하고. 각 부분의 역할을 이해하면서 코드를 살펴보시기 바랍니다.
#include <iostream>
int main() {
int max = 2147483647; // int 최댓값
std::cout << max << std::endl; // 2147483647
std::cout << max + 1 << std::endl; // -2147483648 (오버플로우!)
long long big = 2147483647LL;
std::cout << big + 1 << std::endl; // 2147483648 (정상)
return 0;
}
주의: 코딩테스트에서 자주 나오는 함정입니다.
같이 보면 좋은 글 (내부 링크)
이 주제와 연결되는 다른 글입니다.
- C++ string | “문자열 처리” 완벽 가이드 [실전 함수 총정리]
- C++ 클래스와 객체 | “초보자를 위한” 완벽 가이드 [그림으로 이해]
- C++ 포인터 | “어렵다는 포인터” 5분 만에 이해하기 [그림으로 설명]