ฟังก์ชัน memcpy()
memcpy() คัดลอกข้อมูลจาก source ไป destination จำนวน n ไบต์ ไม่จัดการ overlapping (หากทับกันพฤติกรรม undefined)
Prototype
void* memcpy(void* dest, const void* src, size_t n);
Implementation
#include <cstddef> // size_t
void* myMemcpy(void* dest, const void* src, size_t n) {
unsigned char* d = static_cast<unsigned char*>(dest);
const unsigned char* s = static_cast<const unsigned char*>(src);
for (size_t i = 0; i < n; i++) {
d[i] = s[i];
}
return dest;
}
ฟังก์ชัน memmove()
memmove() คล้าย memcpy() แต่ จัดการ overlapping ได้อย่างถูกต้อง โดยคัดลอกผ่าน temporary buffer หรือคัดลอกย้อนกลับ
Prototype
void* memmove(void* dest, const void* src, size_t n);
Implementation (ใช้ Temporary Buffer)
void* myMemmove(void* dest, const void* src, size_t n) {
if (dest == src || n == 0) return dest;
unsigned char* d = static_cast<unsigned char*>(dest);
const unsigned char* s = static_cast<const unsigned char*>(src);
// จัดสรร temporary buffer
unsigned char* temp = new unsigned char[n];
// คัดลอก src -> temp
for (size_t i = 0; i < n; i++) {
temp[i] = s[i];
}
// คัดลอก temp -> dest
for (size_t i = 0; i < n; i++) {
d[i] = temp[i];
}
delete[] temp;
return dest;
}
Implementation แบบไม่ใช้ Extra Memory (Optimized)
void* myMemmoveOpt(void* dest, const void* src, size_t n) {
unsigned char* d = static_cast<unsigned char*>(dest);
const unsigned char* s = static_cast<const unsigned char*>(src);
if (d < s) {
// src อยู่หน้า dest: คัดลอกไปข้างหน้า (forward) ปลอดภัย
for (size_t i = 0; i < n; i++) {
d[i] = s[i];
}
} else if (d > s) {
// src อยู่หลัง dest: คัดลอกย้อนกลับ (backward) เพื่อไม่ทับข้อมูลที่ยังไม่อ่าน
for (size_t i = n; i > 0; i--) {
d[i - 1] = s[i - 1];
}
}
// d == s: ไม่ต้องทำอะไร
return dest;
}
ตัวอย่างการใช้งาน
#include <iostream>
#include <cstring>
using namespace std;
int main() {
// memcpy example
char src1[] = "Hello!";
char dest1[100];
myMemcpy(dest1, src1, strlen(src1) + 1); // +1 สำหรับ null terminator
cout << "Copied string: " << dest1 << endl;
// memmove example - overlapping
char buffer[] = "abcdefghijklmnop";
cout << "Before memmove: " << buffer << endl;
// คัดลอก "abcdef" (6 chars) จาก index 0 ไป index 5 (ทับกัน)
myMemmoveOpt(buffer + 5, buffer, 6);
cout << "After memmove: " << buffer << endl;
// ผลลัพธ์: "abcdeabcdefghijkl" (6 chars แรกถูกคัดลอกไปทับที่ index 5)
return 0;
}
ผลลัพธ์
Copied string: Hello! Before memmove: abcdefghijklmnop After memmove: abcdeabcdefghijkl
ความแตกต่างสำคัญ
| ด้าน | memcpy | memmove |
|---|---|---|
| Overlapping | Undefined Behavior | Safe (ถูกต้อง) |
| Performance | เร็วกว่า (ไม่ต้องเช็ค) | ช้ากว่าเล็กน้อย |
| Use case | รู้แน่ว่าไม่ทับกัน | ไม่แน่ใจหรือรู้ว่าทับกัน |
สรุป
memcpy ใช้เมื่อแน่ใจว่า memory regions ไม่ทับกัน (เร็วกว่า) memmove ใช้เมื่ออาจทับกันหรือไม่แน่ใจ (ปลอดภัย) ใน C++ สมัยใหม่ ควรใช้ std::copy, std::copy_backward, หรือ std::memmove แทนเพื่อ type safety