ฟังก์ชัน memmove() คล้าย memcpy() แต่ รองรับ Overlapping Memory Regions ทำงานถูกต้องแม้ Source และ Destination จะทับซ้อนกัน อยู่ใน Header <string.h>
ไวยากรณ์
#include <string.h>
void *memmove(void *dest, const void *src, size_t n);
dest- Destination Buffersrc- Source Buffern- จำนวน Bytes- คืนค่า:
dest
ตัวอย่าง
#include <stdio.h>
#include <string.h>
int main() {
char src[] = "Secondstring";
char dest[] = "Firststring";
// ย้าย 9 bytes จาก src ไป dest (Overlap ไม่ได้ในตัวอย่างนี้ แต่ memmove ทำงานได้)
memmove(dest, src, 9);
printf("New arrays: %s\t%s\n", dest, src);
return 0;
}
ผลลัพธ์
New arrays: Secondstrng Secondstring
ความแตกต่างหลัก: Overlapping Behavior
กรณี Overlap: memmove() ทำงานถูกต้อง
char str[] = "abcdefghijklmnop";
printf("Before: %s\n", str); // abcdefghijklmnop
// Copy 8 bytes from index 4 to index 0 (Overlap!)
memmove(str, str + 4, 8);
printf("After: %s\n", str); // efghijklmnop
memcpy() กับกรณีเดียวกัน: Undefined Behavior
char str[] = "abcdefghijklmnop";
// memcpy(str, str + 4, 8); // UB! ผลลัพธ์ไม่แน่นอน
วิธีการทำงานของ memmove() (Implementation Strategy)
// Pseudocode
void *memmove(void *dest, const void *src, size_t n) {
if (dest < src) {
// Forward Copy: Copy from Beginning
// Safe: Destination เขียนทับ Source ที่ยังไม่ได้อ่าน
for (i = 0; i < n; i++) dest[i] = src[i];
} else if (dest > src) {
// Backward Copy: Copy from End
// Safe: Destination เขียนทับ Source ที่อ่านแล้ว
for (i = n; i > 0; i--) dest[i-1] = src[i-1];
}
return dest;
}
ตารางเปรียบเทียบ
| คุณสมบัติ | memcpy() | memmove() |
|---|---|---|
| Overlap Safety | ✗ Undefined Behavior | ✓ Safe (Handles Both Directions) |
| Performance | เร็วกว่าเล็กน้อย | ช้ากว่าเล็กน้อย (Branch Check) |
| Use Case | Non-overlapping, Performance Critical | Overlapping หรือ Unknown |
| Implementation | Simple Forward Copy | Direction-aware Copy |
เมื่อไหร่ควรใช้ memmove()
- Shift Array Elements (Insert/Delete ใน Array)
- Buffer Management (Circular Buffers)
- String Manipulation ที่ Overlap
- เมื่อไม่แน่ใจว่า Overlap หรือไม่ (Safe Choice)
ตัวอย่าง: Insert Element ใน Array
void insertInt(int *arr, int *size, int capacity, int index, int value) {
if (*size >= capacity) return; // Full
// Shift elements right (Overlap: dest = src + 1)
memmove(&arr[index + 1], &arr[index], (*size - index) * sizeof(int));
arr[index] = value;
(*size)++;
}
int main() {
int arr[10] = {1, 2, 3, 4, 5};
int size = 5;
insertInt(arr, &size, 10, 2, 99); // Insert 99 at index 2
// arr = {1, 2, 99, 3, 4, 5}
return 0;
}
ตัวอย่าง: Delete Element จาก Array
void deleteInt(int *arr, int *size, int index) {
if (index < 0 || index >= *size) return;
// Shift elements left (Overlap: dest = src - 1)
memmove(&arr[index], &arr[index + 1], (*size - index - 1) * sizeof(int));
(*size)--;
}
สรุป
memmove() คือ Safe Version ของ memcpy() สำหรับ Overlapping Regions ใช้เมื่อ Source และ Destination อาจทับซ้อนกัน (Shift Arrays, Buffer Operations) ช้ากว่า memcpy เล็กน้อย แต่ปลอดภัยกว่า