이 글은 반복문에서 int 타입과 size_t 타입을 사용할 때의 차이에 대해 정리한 글입니다.
C++로 알고리즘을 풀거나 개발을 하다보면 습관적으로 for (int i = 0; i < ...)를 사용하곤 한다. 대부분의 경우에서는 int를 사용하면 아무 문제 없이 잘 돌아간다.
하지만... 가끔...! "signed / unsigned mismatch"와 같은 컴파일러 경고가 뜨기도 한다.
오늘도 알고리즘 문제를 풀다가 갑자기, 🤔 int와 size_t 타입의 차이가 뭐지? 라는 의문이 들었고, 왜 C++ 표준에서 인덱스 타입으로 size_t를 권장하는지, 그리고 언제 int를 사용하면 위험한지 정리해보고자 한다.
근본적인 차이: 부호(Sign)의 유무
가장 기초적인 차이는 바로 음수를 다룰 수 있는가?이다.
int(Signed Integer) : 음수(-), 0, 양수(+) 모두 표현 가능size_t(Unsigned Integer) : 0과 양수(+)만 표현 가능 (음수 불가능)
🤔 왜 중요한가? → "의도"의 차이
배열에서의 인덱스는 "순서"를 의미한다. -1번째나 -5번째 데이터라는 것은 존재하지 않기 때문에, 인덱스는 태생적으로 음수가 될 필요가 없는 데이터이다.
C++ 표준 라이브러리(std::vector, array 등)의 .size() 함수가 size_t를 반환하는 이유도 이와 같은 이유이다.
따라서, 반복문 변수 i를 size_t로 선언하는 것은 '이 변수는 절대 음수가 되지 않는다'는 코딩의 의도를 명확히 하는 것이다.
결정적 이유: 데이터 범위와 오버플로우
int를 고집하다가 프로그램이 터질 수 있는 치명적인 이유이다. 특히 64비트 시스템에서 대용량 데이터를 다룰 때 문제가 된다.
int(보통 32비트): 표현 범위 약 -21억 ~ +21억size_t(64비트 기준): 표현범위 약 0 ~ 1,844경... (사실 상 메모리 전체)
💥 시나리오: 데이터가 30억 개라면?
만약 벡터 vec에 데이터가 30억 개가 들어있다고 가정하면,
// 위험한 코드!
for (int i = 0; i < vec.size(); i++) {
// ...
}
- 변수
i는int이므로 21억(약 2,147,483,647)까지는 잘 증가함 - 하지만 21억을 넘어서
i++를 하는 순간 오버플로우(Overflow) 발생 i의 값은 오버플로우에 의해 약 -21억으로 변함- -21억은 30억(
vec.size())보다 작기 때문에 루프는 끝나지 않고 무한 루프에 빠지거나 잘못된 메모리 참조로 프로그램이 죽어버림 (Segfault)
👉 즉, int를 사용하면 21억 개 이상의 데이터를 처리할 수 없다. 반면, size_t는 물리 메모리가 허용하는 한 모든 크기를 커버할 수 있다.
⚠️ size_t를 사용하면 안되는 경우: 역순 반복
그렇다 해서 무조건 size_t를 사용하는 것은 정답이 아니다. 뒤에서 앞으로 도는 반복문(역순)을 짤 때 size_t를 사용하면 안된다.
// 5, 4, 3, 2, 1, 0 순으로 돌고 끝나길 기대함
for (size_t i = 5; i >= 0; i--) {
cout << i << endl;
}
변수 i가 0일 때 i-- 연산을 수행하면 -1이 되어야 하지만 size_t 타입에서는 음수가 없기 떄문에 -1 대신에 표현 가능한 가장 큰 수 (약 1,844경)로 변해버린다.
언더플로우(Underflow)가 발생하는 것인데, 이 값은 당연히 0보다 크기 때문에 루프가 멈추지 않는다.
👉 역순 반복이 필요할 때는 그냥 int를 쓰거나 문법을 수정할 필요가 있다.
결론 및 요약
현대적인 C++에서는 인덱스를 직접 관리하는 것보다 Range-based for loop를 사용하는 것이 가장 깔끔하고 안전하다.
// 인덱스가 꼭 필요한 게 아니라면 이게 최고!
for (const auto& val : vec) {
// val 사용
}
📝 int와 size_t 비교
| 구분 | int |
size_t |
| 의미 | 일반 정수 (음수 포함) | 메모리 크기 / 인덱스 전용 |
| 범위 | 약 21억 한계 (32 bit) | 메모리 전체 커버 가능 (64 bit) |
| 위험성 | 대용량 데이터에서 오버플로우 | 역순 반복(i >= 0) 시 무한 루프 |
| 추천 | 간단한 계산, 역순 반복 | 배열/벡터 인덱싱, .size() 비교 |
👉 결론: vec.size()와 비교하는 정방향 for문에서는 size_t를 사용하는 것이 정석이며 버그를 예방하는 좋은 습관이다!
'🖥️ Dev > Language' 카테고리의 다른 글
| [C++] C++의 변수와 상수 (0) | 2025.07.05 |
|---|---|
| [C++] C++ 프로그램 개요와 구조 (0) | 2025.07.05 |
| [Java] Java의 연산자 (산술, 비교, 논리, 대입 등) (4) | 2025.07.05 |
| [Java] Java의 변수와 상수 (0) | 2025.07.04 |
| [Java] Java의 기본 데이터 타입 (1) | 2025.06.24 |
since 2025.01.27. ~ 개발자를 향해....🔥