Zero-based Indexing มาจากแนวคิด Pointer Arithmetic และ Memory Offset — ไม่ใช่การนับลำดับ (Ordinal)
Memory Model Explanation
Array เป็น Contiguous Memory Block แต่ละ Element มีขนาดเท่ากัน
// สมมติ int[] เริ่มที่ Address 0xFF000, int = 4 bytes
// Elements: {35, 23, 67, 88, 90}
Address Value
0xFF000 35 ← Index 0 (Offset 0 * 4 = 0)
0xFF004 23 ← Index 1 (Offset 1 * 4 = 4)
0xFF008 67 ← Index 2 (Offset 2 * 4 = 8)
0xFF012 88 ← Index 3 (Offset 3 * 4 = 12)
0xFF016 90 ← Index 4 (Offset 4 * 4 = 16)
Formula: Address = BaseAddress + Index * ElementSize
Index 0 = Offset 0 = Base Address — ทางคณิตศาสตร์เป็น Natural Starting Point
เหตุผลทางประวัติศาสตร์
- BCPL (1967): Pointer-based,
ptr!0= First Element - B (1969): รองชาตของ BCPL
- C (1972): ใช้ Zero-based ต่อเนื่องมา —
a[i]≡*(a + i) - C++, Java, C#, JavaScript, Python, Go, Rust... ทั้งหมด繼承มาจาก C
ข้อดีทางคณิตศาสตร์และการเขียนโปรแกรม
| Scenario | Zero-based | One-based |
|---|---|---|
| Empty Array Length | Length = 0, Index Range: ∅ | Length = 0, Index Range: ? (Inconsistent) |
| Single Element | Index 0, Length 1 | Index 1, Length 1 |
| Slice/Subarray [start, end) | Length = end - start ✅ | Length = end - start + 1 ❌ |
| Modulo (Circular Buffer) | i % n Natural | (i-1) % n + 1 Awkward |
| Multi-dim Index Calc | row * cols + col | (row-1)*cols + (col-1) |
C# Specifics
int[] arr = new int[10]; // Length = 10, Valid Indices: 0..9
// Loop Pattern
for (int i = 0; i < arr.Length; i++) { // i < Length (Not <=)
arr[i] = i + 10;
}
// Foreach (No Index Needed)
foreach (int val in arr) { }
// Span/Slice (Modern)
var slice = arr.AsSpan(2, 3); // Index 2, Length 3 → Elements 2,3,4
ภาษาที่ใช้ One-based (เพื่ออ้างอิง)
- MATLAB, R, Lua, Julia, Fortran, Visual Basic 6, SQL (LIMIT/OFFSET บางระบบ)
- Human Language: "First, Second, Third" (Ordinal Numbers)
สรุป
- Zero-based = Offset from Base Address (Pointer Arithmetic)
- สอดคล้องกับ Memory Layout, Math, Slicing, Modulo
- C# สืบทอดมาจาก C/C++/Java — Standard สากลใน Systems Programming
- Length = Number of Elements, Last Index = Length - 1