size_t และ int เป็น Signed/Unsigned Integer Types ที่ใช้กันอย่างแพร่หลาย แต่มีความหมายและขนาดต่างกันจริงๆ การใช้ผิดที่อาจนำไปสู่ Bugs ที่หาไม่ออก
คำจำกัดความมาตรฐาน
| คุณสมบัติ | size_t | int |
|---|---|---|
| Signedness | Unsigned (เสมอ) | Signed (เสมอ) |
| ขนาดขั้นต่ำ | 16-bit | 16-bit |
| วัตถุประสงค์ | ขนาด Object / Array Index / Loop Counter | Integer Arithmetic ทั่วไป |
| Header | <cstddef> (หรือ <cstdlib>) | Built-in Keyword |
| ขนาดบน 64-bit Linux | 64-bit (8 bytes) | 32-bit (4 bytes) |
| ขนาดบน 64-bit Windows (LLP64) | 64-bit | 32-bit |
| ขนาดบน 32-bit Systems | 32-bit | 32-bit |
ปัญหาทั่วไปจากการใช้ผิด
1. Signed/Unsigned Mismatch Warning
std::vector<int> v(10);
for (int i = 0; i < v.size(); ++i) { } // Warning: signed/unsigned comparison
// v.size() คืน size_t (unsigned)
แก้: ใช้ size_t i หรือ auto i หรือ Cast: static_cast<int>(v.size())
2. Underflow ใน Loop Downward
for (size_t i = n; i >= 0; --i) { } // Infinite Loop! size_t ไม่มีค่าลบ
// i = 0 -> --i = SIZE_MAX (ใหญ่มาก)
แก้: ใช้ for (auto i = n; i-- > 0; ) หรือ Signed Type
3. Pointer Arithmetic & Array Indexing
int arr[100];
size_t idx = 50;
int* ptr = arr + idx; // ถูกต้อง: Pointer Arithmetic ใช้ size_t (ptrdiff_t จริงๆ)
เมื่อไหร่ควรใช้ตัวไหน?
- size_t: Array Index, Container Size, Loop Counter (Forward), Memory Size,
sizeofResult - int: General Math, Negative Values, Loop Counter (Backward), API ที่กำหนดเป็น int
- ptrdiff_t: Pointer Difference, Signed Index (Can be Negative)
- intptr_t / uintptr_t: Pointer-to-Integer Casting
Modern C++ Best Practice
// ใช้ auto ให้คอมไพเลอร์ดึง Type ให้ (C++11)
for (auto i = 0; i < container.size(); ++i) { } // i เป็น size_t
// Range-based for (C++11) - หลีกเลี่ยง Index ทั้งหมด
for (const auto& elem : container) { }
// Iterator-based
for (auto it = vec.begin(); it != vec.end(); ++it) { }
// std::ssize() (C++20) - คืน Signed Size
for (std::ptrdiff_t i = std::ssize(vec) - 1; i >= 0; --i) { }
สรุป
size_t คือ Type สำหรับ "ขนาด" และ "Index" (Unsigned, ขนาดเท่า Pointer) int คือ Signed Integer ทั่วไป 32-bit บนระบบ 64-bit ส่วนใหญ่ อย่าใช้สลับกัน โดยเฉพาะ Comparison และ Backward Loop ใช้ auto, Range-based For, หรือ std::ssize() เพื่อลดปัญหา