0Pricing
C Academy · บทเรียน

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 ในทันที — ไม่ต้องติดตั้งในเครื่องของคุณ

บทเรียนทั้งหมดในหลักสูตรนี้

  1. strlen, strcpy, strcat
  2. strcmp และการเปรียบเทียบ
  3. strtok และการแยกโทเคน
  4. memcpy และ memset
← กลับไปที่ C Academy