ขยายด้วย realloc
ปรับขนาดอาร์เรย์แบบไดนามิก
ขยายด้วย realloc เป็นบทเรียน C Academy ฟรีบน CoddyKit นี่คือบทเรียนที่ 2 จากทั้งหมด 4 บทเรียน คุณสามารถอ่านบทเรียนทั้งหมดด้านล่างฟรี — จากนั้นลองปฏิบัติด้วยตัวคุณเองในเบราว์เซอร์พร้อมตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7 บทเรียนนี้เป็นส่วนหนึ่งของเส้นทางการเรียน C Academy และความก้าวหน้าของคุณจะซิงค์ข้ามเว็บและแอป CoddyKit คอร์ส C Academy มีบทเรียนทั้งหมด 4 บทเรียน
เมื่อ malloc ครั้งเดียวไม่เพียงพอ
บางครั้งคุณจัดสรรแถวลำดับ เติมข้อมูลแล้วจึงพบว่าต้องการพื้นที่เพิ่ม คุณไม่สามารถเขียนเลยจุดสิ้นสุดไปได้
realloc ช่วยให้คุณปรับขนาดบล็อกบนฮีปที่มีอยู่ โดยรักษาข้อมูลเดิมที่อยู่ในบล็อกไว้
รูปแบบการเรียก realloc
realloc(ptr, new_bytes) รับตัวชี้เดิมและขนาดใหม่ทั้งหมดในหน่วยไบต์
ฟังก์ชันจะคืนตัวชี้ไปยังบล็อกที่มีขนาดใหม่ ข้อมูลส่วนแรกจะคงอยู่จนถึงขนาดที่เล็กกว่าระหว่างขนาดเดิมกับขนาดใหม่
int *bigger = realloc(a, new_n * sizeof(*a));บล็อกอาจถูกย้าย
realloc อาจขยายบล็อกในตำแหน่งเดิม หรืออาจจัดสรรบล็อกใหม่ คัดลอกข้อมูลของคุณ แล้วคืนบล็อกเดิม
ไม่ว่ากรณีใด ตัวชี้เดิมอาจใช้ไม่ได้อีกต่อไป คุณต้องใช้ตัวชี้ที่ฟังก์ชันคืนให้ตั้งแต่นี้เป็นต้นไป
a = realloc(a, new_n * sizeof(*a));
/* the old value of a may no longer be valid */กับดักการกำหนดค่าให้ตัวเอง
การเขียน a = realloc(a, ...) ดูเป็นระเบียบแต่มีอันตราย หาก realloc คืนค่า NULL คุณจะเขียนทับ a และสูญเสียตัวชี้เดิม ทำให้บล็อกเก่ารั่วไหล
ให้ใช้ตัวแปรชั่วคราวแทน
int *tmp = realloc(a, new_n * sizeof(*a));
if (tmp == NULL) { /* a is still valid */ return 1; }
a = tmp;การขยายแถวลำดับอย่างปลอดภัย
โปรแกรมนี้จัดสรรจำนวนเต็ม 3 ตัว แล้วขยายเป็น 6 ตัวด้วย realloc โดยรักษาค่าสามค่าแรกไว้
#include <stdio.h>
#include <stdlib.h>
int main(void) {
int *a = malloc(3 * sizeof(*a));
if (!a) return 1;
for (int i = 0; i < 3; i++) a[i] = i + 1;
int *tmp = realloc(a, 6 * sizeof(*a));
if (!tmp) { free(a); return 1; }
a = tmp;
for (int i = 3; i < 6; i++) a[i] = i + 1;
for (int i = 0; i < 6; i++) printf("%d\n", a[i]);
free(a);
return 0;
}ไบต์ใหม่ยังไม่ได้กำหนดค่า
เมื่อคุณขยายบล็อก พื้นที่เพิ่มเติมตอนท้ายจะมีค่าขยะเช่นเดียวกับหน่วยความจำจาก malloc ที่เพิ่งจัดสรร
realloc รักษาข้อมูลเดิมไว้ แต่ไม่ได้กำหนดค่าเป็นศูนย์ให้พื้นที่ใหม่ คุณต้องกำหนดค่าให้พื้นที่นั้นก่อนอ่าน
a = realloc(a, 6 * sizeof(*a));
for (int i = 3; i < 6; i++) a[i] = 0; /* clear new slots */กลยุทธ์การเพิ่มเป็นสองเท่า
การเรียก realloc สำหรับสมาชิกทุกตัวช้า เทคนิคคลาสสิกคือเพิ่มความจุเป็นสองเท่าทุกครั้งที่พื้นที่ไม่พอ
วิธีนี้ทำให้จำนวนครั้งที่ปรับขนาดใหม่มีน้อยเมื่อแถวลำดับเติบโต และให้ประสิทธิภาพโดยเฉลี่ยที่ดี
if (count == cap) {
cap = cap ? cap * 2 : 4;
int *tmp = realloc(a, cap * sizeof(*a));
if (!tmp) { free(a); return 1; }
a = tmp;
}สร้างแถวลำดับด้วยการเพิ่มต่อท้าย
โปรแกรมนี้เริ่มจากแถวลำดับว่าง แล้วเพิ่มตัวเลขต่อท้าย โดยเพิ่มความจุเป็นสองเท่าเมื่อจำเป็น
#include <stdio.h>
#include <stdlib.h>
int main(void) {
int *a = NULL;
size_t count = 0, cap = 0;
for (int v = 1; v <= 5; v++) {
if (count == cap) {
cap = cap ? cap * 2 : 2;
int *tmp = realloc(a, cap * sizeof(*a));
if (!tmp) { free(a); return 1; }
a = tmp;
}
a[count++] = v;
}
for (size_t i = 0; i < count; i++) printf("%d\n", a[i]);
free(a);
return 0;
}realloc(NULL, n) ทำงานเหมือน malloc
หากส่ง NULL เป็นตัวชี้ realloc จะทำงานเหมือน malloc ทุกประการ
ด้วยเหตุนี้การเริ่มต้นด้วย a = NULL จึงใช้ได้ในลูปเพิ่มความจุเป็นสองเท่า เพราะ realloc ครั้งแรกจะจัดสรรบล็อกเริ่มต้น
int *a = NULL;
a = realloc(a, 4 * sizeof(*a)); /* same as malloc(4 * sizeof(*a)) */การลดขนาดบล็อก
realloc ยังสามารถทำให้บล็อกมีขนาดเล็กลงได้ ข้อมูลจนถึงขนาดใหม่จะถูกเก็บไว้ ส่วนที่เหลือจะถูกทิ้ง
การลดขนาดอาจคืนหน่วยความจำกลับมาได้ แต่การทำงานจริงของแต่ละระบบยังมีสิทธิ์เก็บบล็อกขนาดใหญ่กว่าไว้
int *tmp = realloc(a, 2 * sizeof(*a)); /* down from more */
if (tmp) a = tmp;หลีกเลี่ยงค่าล้นในการคำนวณ
เมื่อความจุเพิ่มขึ้นมาก cap * sizeof(*a) อาจมีค่าล้นชนิดข้อมูล size_t และวนกลับกลายเป็นตัวเลขขนาดเล็กมาก
สำหรับอาร์เรย์ขนาดใหญ่มาก ให้ตรวจป้องกันการคูณล้น หรือใช้ reallocarray บนระบบที่รองรับ
if (cap > SIZE_MAX / sizeof(*a)) { /* overflow */ return 1; }
int *tmp = realloc(a, cap * sizeof(*a));ตรวจสอบความเข้าใจอย่างรวดเร็ว
ทดสอบความเข้าใจเกี่ยวกับ realloc ของคุณ
ทบทวน
realloc ปรับขนาดบล็อกบนฮีพและอาจย้ายบล็อก ดังนั้นให้ใช้พอยน์เตอร์ที่ส่งคืนมาเสมอ
กำหนดค่าให้ตัวแปรชั่วคราว เพื่อไม่ให้การทำงานล้มเหลวทำให้บล็อกเดิมรั่วไหล ขยายขนาดเป็นสองเท่าเพื่อความเร็ว กำหนดค่าเริ่มต้นให้ช่องใหม่ และจำไว้ว่า realloc(NULL, n) เทียบเท่ากับ malloc บทถัดไป คุณจะห่อหุ้มตรรกะนี้เป็นชนิดเวกเตอร์ที่นำกลับมาใช้ซ้ำได้
คำถามที่พบบ่อย
บทเรียน “ขยายด้วย realloc” ฟรีหรือไม่
ใช่ — ข้อความเต็มของ “ขยายด้วย realloc” ฟรีให้อ่านที่นี่บนเว็บ เพื่อปฏิบัติแบบโต้ตอบ (ตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7) และปลดล็อคส่วนที่เหลือของคอร์ส C Academy ให้อัปเกรดเป็น CoddyKit PRO คอร์ส C Academy มีบทเรียนทั้งหมด 4 บทเรียน
คุณจะเรียนรู้อะไรในบทเรียน “ขยายด้วย realloc”
ปรับขนาดอาร์เรย์แบบไดนามิก คุณปฏิบัติ C Academy ด้วยโค้ดที่ใช้งานได้จริงที่คุณเรียกใช้โดยตรงในเบราว์เซอร์ และติวเตอร์ AI ตลอด 24/7 ตอบคำถามของคุณขณะที่คุณไปผ่านบทเรียน
คุณต้องมีประสบการณ์ก่อนที่จะเริ่มเรียน C Academy หรือไม่
ไม่จำเป็นต้องมีประสบการณ์มาก่อน C Academy บน CoddyKit ออกแบบมาสำหรับผู้เริ่มต้นไปจนถึงผู้เรียนขั้นสูง คุณสามารถเริ่มต้นที่นี่หรือเริ่มจากตัวแรกและเรียนด้วยความเร็วของคุณเอง นี่คือบทเรียนที่ 2 จากทั้งหมด 4 บทเรียน
บทเรียน “ขยายด้วย realloc” ใช้เวลานานแค่ไหน
บทเรียน CoddyKit ส่วนใหญ่ใช้เวลาประมาณ 5–10 นาที แต่ละบทเรียนจึงสั้นและเป็นแบบโต้ตอบ คุณสามารถก้าวหน้าอย่างต่อเนื่องและกลับมาเรียนต่อจากตรงที่เพิ่งหยุดบนเว็บและแอปได้เลย
ฉันเขียนและรันโค้ดในบทเรียน C Academy นี้ได้ไหม
ได้ บทเรียน C Academy ทุกบทมีตัวแก้ไขโค้ดในตัว คุณจึงเขียนและรันโค้ดจริงได้เลยในเบราว์เซอร์ และได้รับข้อเสนอแนะจาก AI ในทันที — ไม่ต้องติดตั้งในเครื่องของคุณ