memcpy และ memset
ฟังก์ชันหน่วยความจำดิบ
memcpy และ memset เป็นบทเรียน C Academy ฟรีบน CoddyKit นี่คือบทเรียนที่ 4 จากทั้งหมด 4 บทเรียน คุณสามารถอ่านบทเรียนทั้งหมดด้านล่างฟรี — จากนั้นลองปฏิบัติด้วยตัวคุณเองในเบราว์เซอร์พร้อมตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7 บทเรียนนี้เป็นส่วนหนึ่งของเส้นทางการเรียน C Academy และความก้าวหน้าของคุณจะซิงค์ข้ามเว็บและแอป CoddyKit คอร์ส C Academy มีบทเรียนทั้งหมด 4 บทเรียน
ฟังก์ชันหน่วยความจำดิบ
ต่างจากฟังก์ชันสตริง memcpy และ memset ทำงานกับไบต์ดิบและไม่สนใจตัวสิ้นสุดค่าว่าง
ฟังก์ชันเหล่านี้ประกาศอยู่ใน <string.h> และทำงานกับจำนวนไบต์ที่คุณระบุ จึงใช้ได้ทั่วไปกับข้อมูลทุกชนิด
#include <stdio.h>
#include <string.h>
int main(void) {
int src[] = {1, 2, 3};
int dest[3];
memcpy(dest, src, sizeof(src));
printf("%d %d %d\n", dest[0], dest[1], dest[2]);
return 0;
}รูปแบบการประกาศ memcpy
void *memcpy(void *dest, const void *src, size_t n);
ฟังก์ชันนี้คัดลอกไบต์จำนวน n พอดีจาก src ไปยัง dest และส่งกลับ dest ใช้ sizeof เพื่อหาจำนวนไบต์ที่ถูกต้อง
#include <stdio.h>
#include <string.h>
int main(void) {
char src[] = "copy me";
char dest[16];
memcpy(dest, src, strlen(src) + 1);
printf("%s\n", dest);
return 0;
}การนับไบต์อย่างถูกต้อง
จำนวนที่ระบุเป็นไบต์ ไม่ใช่จำนวนสมาชิก สำหรับอาร์เรย์ของ int คุณต้องคูณด้วย sizeof(int)
การใช้ sizeof(array) กับอาร์เรย์จริงจะให้ขนาดรวมเป็นไบต์โดยอัตโนมัติ
#include <stdio.h>
#include <string.h>
int main(void) {
double a[4] = {1.5, 2.5, 3.5, 4.5};
double b[4];
memcpy(b, a, 4 * sizeof(double));
printf("%.1f %.1f\n", b[0], b[3]);
return 0;
}บริเวณหน่วยความจำต้องไม่ทับซ้อนกัน
memcpy มีพฤติกรรมไม่กำหนดหากบริเวณต้นทางและปลายทางทับซ้อนกัน
เมื่อช่วงหน่วยความจำอาจทับซ้อนกัน (เช่น การเลื่อนสมาชิกภายในอาร์เรย์เดียว) ให้ใช้ memmove แทน ซึ่งจัดการการทับซ้อนได้อย่างปลอดภัย
#include <stdio.h>
#include <string.h>
int main(void) {
char buf[] = "ABCDEF";
memmove(buf + 2, buf, 4);
printf("%s\n", buf);
return 0;
}รูปแบบการประกาศ memset
void *memset(void *ptr, int value, size_t n);
ฟังก์ชันนี้เติมไบต์จำนวน n ที่ ptr ด้วยไบต์ค่า value โดยค่าดังกล่าวจะถูกตีความเป็น unsigned char ดังนั้นจึงมีเพียง 8 บิตล่างสุดที่มีผล
#include <stdio.h>
#include <string.h>
int main(void) {
char buf[6];
memset(buf, 'x', 5);
buf[5] = '\0';
printf("%s\n", buf);
return 0;
}การทำให้หน่วยความจำเป็นศูนย์
การใช้งาน memset ที่พบบ่อยที่สุดคือการล้างบัฟเฟอร์หรือโครงสร้างข้อมูลให้เป็นศูนย์ทั้งหมดก่อนใช้งาน
memset(arr, 0, sizeof(arr)) จะกำหนดทุกไบต์ให้เป็น 0 ซึ่งเป็นค่าศูนย์ที่ถูกต้องสำหรับ int, float และตัวชี้
#include <stdio.h>
#include <string.h>
int main(void) {
int counts[5];
memset(counts, 0, sizeof(counts));
for (int i = 0; i < 5; i++) printf("%d ", counts[i]);
printf("\n");
return 0;
}memset ทำงานทีละไบต์
โปรดระวัง: memset กำหนดค่าให้แต่ละไบต์ ไม่ใช่สมาชิกแต่ละตัว การใช้ฟังก์ชันนี้เติมค่า 1 ให้กับอาร์เรย์ int จะไม่ได้ค่าเป็นหนึ่ง
int แต่ละตัวจะมีทุกไบต์เป็น 0x01 ทำให้ได้ค่า 0x01010101 ไม่ใช่ 1
#include <stdio.h>
#include <string.h>
int main(void) {
int a[2];
memset(a, 1, sizeof(a));
printf("%d\n", a[0]);
return 0;
}การล้างโครงสร้างข้อมูล
memset มีประโยชน์สำหรับกำหนดค่าเริ่มต้นให้โครงสร้างข้อมูลทั้งชุดเป็นศูนย์ด้วยการเรียกครั้งเดียว แทนการกำหนดค่าให้แต่ละฟิลด์ด้วยตนเอง
#include <stdio.h>
#include <string.h>
struct Point { int x; int y; int z; };
int main(void) {
struct Point p;
memset(&p, 0, sizeof(p));
printf("%d %d %d\n", p.x, p.y, p.z);
return 0;
}การคัดลอกโครงสร้างข้อมูล
คุณสามารถคัดลอกโครงสร้างข้อมูลด้วย memcpy ได้ แม้การกำหนดค่าโดยตรง (b = a;) มักทำสิ่งเดียวกันได้อย่างชัดเจนกว่า
ควรใช้ memcpy เมื่อต้องคัดลอกผ่านตัวชี้ทั่วไปชนิด void * ซึ่งไม่มีข้อมูลชนิดกำกับอยู่
#include <stdio.h>
#include <string.h>
struct Rec { int id; char tag; };
int main(void) {
struct Rec a = {42, 'A'};
struct Rec b;
memcpy(&b, &a, sizeof(a));
printf("%d %c\n", b.id, b.tag);
return 0;
}memcmp: การเปรียบเทียบหน่วยความจำ
ฟังก์ชันที่เกี่ยวข้องคือ memcmp(a, b, n) ซึ่งเปรียบเทียบไบต์ดิบจำนวน n ไบต์ และส่งกลับ 0 หากตรงกัน
ต่างจาก strcmp ตรงที่ฟังก์ชันนี้ไม่หยุดเมื่อพบตัวสิ้นสุดค่าว่าง จึงใช้กับข้อมูลไบนารีทุกชนิดได้
#include <stdio.h>
#include <string.h>
int main(void) {
int a[] = {1, 2, 3};
int b[] = {1, 2, 3};
if (memcmp(a, b, sizeof(a)) == 0)
printf("Arrays have identical bytes\n");
return 0;
}เหตุผลที่ฟังก์ชันเหล่านี้ทำงานได้เร็ว
memcpy และ memset มักได้รับการปรับปรุงประสิทธิภาพด้วยภาษาแอสเซมบลี เพื่อย้ายไบต์จำนวนมากต่อคำสั่งหนึ่งคำสั่ง
โดยทั่วไปฟังก์ชันเหล่านี้เร็วกว่าลูปไบต์ที่เขียนขึ้นเองมาก จึงควรเลือกใช้สำหรับการย้ายและการกำหนดค่าเริ่มต้นของข้อมูลจำนวนมาก
#include <stdio.h>
#include <string.h>
int main(void) {
char big[1000];
memset(big, 0, sizeof(big));
printf("Cleared %lu bytes\n", sizeof(big));
return 0;
}ตรวจสอบความเข้าใจอย่างรวดเร็ว
ทดสอบความเข้าใจของคุณเกี่ยวกับการทำงานของ memset ในระดับไบต์
สรุปทบทวน
คุณได้เรียนรู้ฟังก์ชันหน่วยความจำดิบ:
- memcpy คัดลอกไบต์จำนวน n ไบต์ โดยบริเวณหน่วยความจำต้องไม่ทับซ้อนกัน (หากอาจทับซ้อน ให้ใช้ memmove)
- memset เติมไบต์จำนวน n ไบต์ด้วยค่าไบต์เดียว เหมาะอย่างยิ่งสำหรับการทำให้เป็นศูนย์
- จำนวนที่ระบุเป็นไบต์ — ใช้
sizeofและระวังข้อผิดพลาดระหว่างไบต์กับสมาชิก - memcmp เปรียบเทียบไบต์ดิบโดยไม่หยุดที่
'\0'
คำถามที่พบบ่อย
บทเรียน “memcpy และ memset” ฟรีหรือไม่
ใช่ — ข้อความเต็มของ “memcpy และ memset” ฟรีให้อ่านที่นี่บนเว็บ เพื่อปฏิบัติแบบโต้ตอบ (ตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7) และปลดล็อคส่วนที่เหลือของคอร์ส C Academy ให้อัปเกรดเป็น CoddyKit PRO คอร์ส C Academy มีบทเรียนทั้งหมด 4 บทเรียน
คุณจะเรียนรู้อะไรในบทเรียน “memcpy และ memset”
ฟังก์ชันหน่วยความจำดิบ คุณปฏิบัติ C Academy ด้วยโค้ดที่ใช้งานได้จริงที่คุณเรียกใช้โดยตรงในเบราว์เซอร์ และติวเตอร์ AI ตลอด 24/7 ตอบคำถามของคุณขณะที่คุณไปผ่านบทเรียน
คุณต้องมีประสบการณ์ก่อนที่จะเริ่มเรียน C Academy หรือไม่
ไม่จำเป็นต้องมีประสบการณ์มาก่อน C Academy บน CoddyKit ออกแบบมาสำหรับผู้เริ่มต้นไปจนถึงผู้เรียนขั้นสูง คุณสามารถเริ่มต้นที่นี่หรือเริ่มจากตัวแรกและเรียนด้วยความเร็วของคุณเอง นี่คือบทเรียนที่ 4 จากทั้งหมด 4 บทเรียน
บทเรียน “memcpy และ memset” ใช้เวลานานแค่ไหน
บทเรียน CoddyKit ส่วนใหญ่ใช้เวลาประมาณ 5–10 นาที แต่ละบทเรียนจึงสั้นและเป็นแบบโต้ตอบ คุณสามารถก้าวหน้าอย่างต่อเนื่องและกลับมาเรียนต่อจากตรงที่เพิ่งหยุดบนเว็บและแอปได้เลย
ฉันเขียนและรันโค้ดในบทเรียน C Academy นี้ได้ไหม
ได้ บทเรียน C Academy ทุกบทมีตัวแก้ไขโค้ดในตัว คุณจึงเขียนและรันโค้ดจริงได้เลยในเบราว์เซอร์ และได้รับข้อเสนอแนะจาก AI ในทันที — ไม่ต้องติดตั้งในเครื่องของคุณ
บทเรียนทั้งหมดในหลักสูตรนี้
- strlen, strcpy, strcat
- strcmp และการเปรียบเทียบ
- strtok และการแยกโทเคน
- memcpy และ memset