ข้ามไปที่เนื้อหา

Ch7: Arrays

TL;DR: Contiguous Memory Allocation: Array จะจัดสรรหน่วยความจำแบบต่อเนื่องกันเพื่อเก็บกลุ่มของข้อมูลประเภทเดียวกัน โดยเข้าถึงผ่านระบบ Index ที่เริ่มจากศูนย์ และตัวแปรชื่อ Array จะอ้างอิงถึงบล็อกหน่วยความจำทั้งหมด

⚡ Quick Reference

#include <iostream>
#include <iterator>

int main() {
    // type name[size] - ประกาศอาเรย์ขนาดคงที่โดยยังไม่ระบุค่าเริ่มต้น
    int arr1[5];

    // type name[size] = { ... } - ประกาศอาเรย์ขนาดคงที่พร้อมกำหนดค่าเริ่มต้นสมาชิก
    int arr2[5] = {10, 20, 30, 40, 50};

    // type name[] = { ... } - ประกาศอาเรย์โดยละเว้นขนาดเพื่อให้ Compiler คำนวณจากลิสต์
    int arr3[] = {1, 2, 3};

    // sizeof(array) / sizeof(array[0]) - คำนวณขนาดสมาชิกอาเรย์รูปแบบดั้งเดิม (C-style)
    size_t size1 = sizeof(arr2) / sizeof(arr2[0]);

    // std::size(array) - คำนวณขนาดสมาชิกอาเรย์โดยใช้ฟังก์ชันตัวช่วยมาตรฐาน (C++17)
    size_t size2 = std::size(arr2);

    // type name[rows][cols] - ประกาศอาเรย์หลายมิติ (อาเรย์ของอาเรย์)
    int grid[2][3] = {{1, 2, 3}, {4, 5, 6}};

    return 0;
}

🧠 Core Concepts

  • Contiguous Memory Allocation: Array จะจัดสรรหน่วยความจำแบบต่อเนื่องกันเพื่อเก็บกลุ่มของข้อมูลประเภทเดียวกัน โดยเข้าถึงผ่านระบบ Index ที่เริ่มจากศูนย์ และตัวแปรชื่อ Array จะอ้างอิงถึงบล็อกหน่วยความจำทั้งหมด
  • Lack of Bounds Checking: C++ ไม่มีการตรวจสอบขอบเขต (Bounds check) ของ Array ทั้งตอน Compile และ Runtime การเข้าถึง Index ที่เกินขอบเขตจึงสามารถผ่านได้แต่จะนำไปสู่ Undefined behavior
  • Character Array Specialization: Array ของตัวอักษรจะมีความพิเศษตรงที่ หากมี Null Terminator (\0) กำกับท้าย จะถูกมองเป็น C-string ซึ่งรองรับการแสดงผลผ่าน std::cout ได้โดยตรง ต่างจาก Array ประเภทอื่น

⚠️ Pitfalls (Quick Scan)

ข้อผิดพลาด วิธีแก้
การเข้าถึงสมาชิกของ Array เกินขอบเขต ตรวจสอบให้มั่นใจเสมอว่า Index อยู่ในช่วง 0 ถึง size - 1 (Lecture 4)
ประกาศ Array โดยไม่กำหนดค่าเริ่มต้น ใช้ Braced Initialization ({}) เสมอตอนประกาศตัวแปร (Lecture 1)
ไม่ได้ใส่ Null Terminator (\0) ใน Char Array ใช้ String Literal ครอบด้วยฟันหนูคู่ หรือระบุตัวอักษรหลีก \0 ท้ายอาร์เรย์ (Lecture 3)
พยายามประกาศ Array แบบหาขนาดอัตโนมัติ int arr[]; โดยไม่ได้ใส่ค่าเริ่มต้น ใส่ค่าเริ่มต้นในเครื่องหมายปีกกาหรือกำหนดขนาด Array ในวงเล็บเหลี่ยมให้ชัดเจน (Lecture 2)
พยายามพิมพ์ค่า Array ที่ไม่ใช่ตัวอักษรออกทางจอภาพโดยตรง ใช้ลูปเพื่อเข้าถึงและพิมพ์สมาชิกทีละตัว (Lecture 3)
แก้ไขข้อมูลสมาชิกใน Array ที่ถูกประกาศเป็น const ถอด Keyword const ออก หากต้องการเปลี่ยนแปลงสมาชิกในภายหลัง (Lecture 1)
ประกาศขนาด Char Array เล็กกว่าความยาวของ String Literal ต้องจองขนาดให้เท่ากับความยาวข้อความบวกเพิ่มอีกหนึ่งเสมอสำหรับเก็บ Null Terminator (Lecture 3)
ละเว้นการระบุมิติอื่นที่ไม่ใช่มิติตัวซ้ายสุดใน Array หลายมิติ ระบุขนาดของมิติทั้งหมดให้ครบ ยกเว้นมิติด้านซ้ายสุดเท่านั้น (Multi-D lecture)

📖 Full Details

Cause → Effect → Fix พร้อม timestamp (คลิกเพื่อดู) * **การเข้าถึงสมาชิกของ Array เกินขอบเขต** -> **เกิด Undefined behavior, ข้อมูลใน Memory เสียหาย หรือโปรแกรมแครช** -> **ตรวจสอบให้มั่นใจเสมอว่า Index อยู่ในช่วง `0` ถึง `size - 1` (Lecture 4)** * **ประกาศ Array โดยไม่กำหนดค่าเริ่มต้น** -> **Array จะเก็บค่าขยะจากหน่วยความจำ ทำให้การทำงานของโปรแกรมคาดเดาไม่ได้** -> **ใช้ Braced Initialization (`{}`) เสมอตอนประกาศตัวแปร (Lecture 1)** * **ไม่ได้ใส่ Null Terminator (`\0`) ใน Char Array** -> **การพิมพ์ผ่าน `std::cout` จะแสดงผลตัวอักษรขยะจนกว่าจะบังเอิญเจอ Null Byte ในหน่วยความจำ** -> **ใช้ String Literal ครอบด้วยฟันหนูคู่ หรือระบุตัวอักษรหลีก `\0` ท้ายอาร์เรย์ (Lecture 3)** * **พยายามประกาศ Array แบบหาขนาดอัตโนมัติ `int arr[];` โดยไม่ได้ใส่ค่าเริ่มต้น** -> **เกิด Compile-time error เนื่องจาก Compiler ไม่สามารถประเมินขนาด Array ได้** -> **ใส่ค่าเริ่มต้นในเครื่องหมายปีกกาหรือกำหนดขนาด Array ในวงเล็บเหลี่ยมให้ชัดเจน (Lecture 2)** * **พยายามพิมพ์ค่า Array ที่ไม่ใช่ตัวอักษรออกทางจอภาพโดยตรง** -> **โปรแกรมจะพิมพ์ Address ของหน่วยความจำ (Pointer) แทนค่าสมาชิก** -> **ใช้ลูปเพื่อเข้าถึงและพิมพ์สมาชิกทีละตัว (Lecture 3)** * **แก้ไขข้อมูลสมาชิกใน Array ที่ถูกประกาศเป็น `const`** -> **เกิด Compile-time error เนื่องจากค่าคงที่ห้ามแก้ไข** -> **ถอด Keyword `const` ออก หากต้องการเปลี่ยนแปลงสมาชิกในภายหลัง (Lecture 1)** * **ประกาศขนาด Char Array เล็กกว่าความยาวของ String Literal** -> **เกิด Compile-time error เพราะมีตัวเริ่มต้นมากเกินไป (เนื่องจากขาดพื้นที่สำหรับเก็บ `\0`)** -> **ต้องจองขนาดให้เท่ากับความยาวข้อความบวกเพิ่มอีกหนึ่งเสมอสำหรับเก็บ Null Terminator (Lecture 3)** * **ละเว้นการระบุมิติอื่นที่ไม่ใช่มิติตัวซ้ายสุดใน Array หลายมิติ** -> **เกิด Compile-time error เนื่องจาก Compiler คาดเดาขนาดมิติอื่นไม่ได้** -> **ระบุขนาดของมิติทั้งหมดให้ครบ ยกเว้นมิติด้านซ้ายสุดเท่านั้น (Multi-D lecture)**

📎 Repo Files

  • 12.Arrays/12.2DeclaringAndUsingArrays/main.cpp
  • 12.Arrays/12.3SizeOfAnArray/main.cpp
  • 12.Arrays/12.4ArraysOfCharacters/main.cpp
  • 12.Arrays/12.5ArrayBounds/main.cpp
  • 12.Arrays/12.6GeneratingRandomNumbers/main.cpp
  • 12.Arrays/12.7Practice_FortuneTellerV1/main.cpp
  • 12.Arrays/12.8MultiDimensionalArrays/main.cpp
  • 12.Arrays/12.9MultiDimensionalArraysOfCharacters/main.cpp
  • 12.Arrays/12.10Practice_FortuneTellerV2/main.cpp