402 คำ
2 นาที
อะไรคือ Array ในระดับ Memory

เกริ่น#

สวัสดีครับ วันนี้เราจะมาพูดถึงเรื่องของ Array ในระดับ Memory กันครับ หลายคนอาจจะเคยได้ยินคำว่า Array มาบ้างแล้ว แต่ยังไม่แน่ใจว่ามันคืออะไร และทำงานยังไงในระดับ Memory

วันนี้เราจะมาเจาะลึกกันแบบเห็นภาพครับ แต่ก่อนจะไปถึง Array เราขอปูพื้นเรื่อง Pointer กันก่อนนิดนึง เพราะสองอย่างนี้มันผูกกันแน่นมาก

Pointer คืออะไร?#

Pointer คือ ตัวแปรที่เก็บที่อยู่ของตัวแปรอื่นๆ ในหน่วยความจำ (Memory) ซึ่งในภาษา C นั้น Pointer เป็นสิ่งที่สำคัญมาก เพราะมันช่วยให้เราสามารถจัดการกับข้อมูลในหน่วยความจำได้อย่างมีประสิทธิภาพ ตัวอย่าง

int a = 10;
int *p = &a; // p คือ pointer ที่เก็บที่อยู่ของ a
printf("Value of a: %d\n", *p); // ใช้ *p เพื่อเข้าถึงค่าของตัวแปรที่ pointer ชี้ไป

output จะได้

Terminal window
Value of a: 10

แต่ถ้าเราลองเปลี่ยนโค้ดนิดหน่อย

int a = 10;
int *p = &a; // p คือ pointer ที่เก็บที่อยู่ของ a
printf("Value of a: %d\n", *p); // ใช้ *p เพื่อเข้าถึงค่าของตัวแปรที่ pointer ชี้ไป
printf("Pointer of a: %p\n", (void*)p);

output จะได้

Terminal window
Pointer of a: 0x7ffee3bff5ac

จะเห็นได้ว่า pointer เก็บ “ที่อยู่ของตัวแปร” ไม่ใช่ค่าของ a โดยตรง

Pointer ใช้ทำอะไรได้บ้าง?#

Pointer มีประโยชน์มากมายในการเขียนโปรแกรม โดยเฉพาะเวลาที่เราทำงานใกล้กับระดับ memory โดยหลัก ๆ จะมีประโยชน์เด่น ๆ 2 อย่างคือ

  1. ประหยัดหน่วยความจำเวลาส่งข้อมูล
  2. สามารถจัดการแก้ไขข้อมูลได้โดยตรงในหน่วยความจำ

1. ประหยัดหน่วยความจำ#

ในกรณีนี้มักจะเกิดขึ้นกับ struct ก่อนใหญ่ๆ เช่น

#include <stdio.h>
typedef struct {
char name[100];
char description[1000];
int price;
} Product;
void printProductByValue(Product p) {
printf("%s - %d\n", p.name, p.price);
}
void printProductByPointer(Product *p) {
printf("%s - %d\n", p->name, p->price);
}
int main() {
Product p = {"Laptop", "Very powerful laptop...", 50000};
printProductByValue(p); // copy ทั้งก้อน แล้วส่งไปยังฟังก์ชัน
printProductByPointer(&p); // ส่ง address ของ p แทนการ copy ทั้งก้อน
}

ในตัวอย่างนี้ ถ้าเราใช้ printProduct(Product p) เราจะต้อง copy ข้อมูลทั้งหมดของ struct Product ไปยังฟังก์ชัน ซึ่งจะใช้หน่วยความจำมาก แต่ถ้าเราใช้ printProduct(Product *p) เราจะส่งแค่ address ของ struct Product ไปยังฟังก์ชัน ซึ่งจะประหยัดหน่วยความจำมากขึ้น

2. แก้ไขข้อมูลได้โดยตรง#

Pointer ยังช่วยให้เราสามารถแก้ไขข้อมูลได้โดยตรงในหน่วยความจำ เช่น

#include <stdio.h>
void increment(int *p) { // รับ pointer เป็น parameter
(*p)++; // แก้ไขค่าที่ pointer ชี้ไปโดยตรง
}
int main() {
int a = 5;
increment(&a); // ส่ง address ของ a ไปยังฟังก์ชัน
printf("Value of a: %d\n", a); // Output จะเป็น 6 เพราะเราแก้ไขค่าของ a โดยตรงผ่าน pointer
}

Array คืออะไรในระดับ Memory#

กลับมาที่เรื่องของ Array กันต่อ Array คือโครงสร้างข้อมูลที่ใช้เก็บข้อมูลหลาย ๆ ตัวในหน่วยความจำที่ต่อเนื่องกัน โดยที่แต่ละตัวจะมีขนาดเท่ากัน และสามารถเข้าถึงได้ด้วย index

ในภาษา C นั้น Array จะถูกเก็บแบบเรียงติดกันในหน่วยความจำ และในกรณีของ string (char array) ตัวสุดท้ายจะมี null character \0 เพื่อบอกว่าข้อมูลจบแล้ว เช่น

char name[6] = "Hello"; // Array of char ที่เก็บคำว่า "Hello"

เรามาลองเข้าไปดูในโลกของ Memory กันครับ ว่า Array ในระดับลึกมันเป็นยังไง

สมมติว่าเรามี “Hello” และมันถูกเก็บอยู่ที่ตำแหน่ง 0x1000 ในหน่วยความจำ

Terminal window
0x1000: 'H'
0x1001: 'e'
0x1002: 'l'
0x1003: 'l'
0x1004: 'o'
0x1005: '\0' // null character ที่บอกว่าข้อมูลจบแล้ว
WARNING

ข้อมูลใน Array จะถูกเก็บต่อเนื่องกันในหน่วยความจำเสมอ
แต่โครงสร้างข้อมูลอย่าง Linked List จะไม่ได้เก็บข้อมูลต่อเนื่องกัน

สำหรับ Array แบบ dynamic (เช่น Array List หรือ vector) ข้อมูลภายในยังคงเรียงต่อกัน
แต่ตำแหน่งในหน่วยความจำอาจถูกย้ายเมื่อมีการขยายขนาด

Array ใน Function: ทำไมมันกลายเป็น Pointer#

มาถึงแก่นแท้ที่ผมจะสื่อ Array เวลาเอาไปใช้กับ function มัน “ไม่ได้ถูก copy ทั้งก้อน” แต่มันจะถูกแปลง (decay) เป็น pointer ไปยัง element ตัวแรกโดยอัตโนมัติ

void print(int arr[]) {
printf("%d\n", arr[0]);
}

กับ

void print(int *arr) {
printf("%d\n", arr[0]);
}

ทั้งสองฟังก์ชันนี้จะทำงานเหมือนกัน เพราะว่า arr ในฟังก์ชันแรกจะถูกแปลงเป็น pointer ไปยัง element ตัวแรกของ array อยู่ดี แล้วตอนเรียกล่ะ?

int arr[3] = {1, 2, 3};
print(arr);

output จะได้

0x7ffee3bff5a0

ซึ่งก็ไม่ได้ต่างจาก

print(&arr[0]);

สรุป#

ถ้าคุณเข้าใจแนวคิดพวกนี้แล้ว ไม่ว่าจะเป็น array, pointer และการทำงานของ memory คุณจะสามารถนำพื้นฐานนี้ไปต่อยอดในภาษาอื่น ๆ ได้อีกมาก เช่น Go หรือ Rust

ถึงแม้แต่ละภาษาจะมีวิธีจัดการ pointer หรือ memory ที่แตกต่างกันออกไป แต่แนวคิดพื้นฐานอย่าง “การอ้างอิงตำแหน่งในหน่วยความจำ” และ “การเข้าถึงข้อมูลผ่าน address” ยังคงเหมือนเดิม

พูดง่าย ๆ คือ syntax อาจเปลี่ยน แต่ mindset เดิมยังใช้ได้เสมอ

NOTE

Rust → ไม่มี pointer แบบ C ตรง ๆ แต่ใช้ reference + ownership ถ้าคุณเคยทำ malloc แล้ว free ram ไม่หมดคุณจะเข้าใจแนวคิดนี้ได้ดีขึ้น

อะไรคือ Array ในระดับ Memory
https://twichai.com/posts/array/
ผู้เขียน
Teerasak Wichai
เผยแพร่เมื่อ
2026-04-06
สัญญาอนุญาต
CC BY-NC-SA 4.0