C Academy · 课时

memcpy 与 memset

原始内存函数

第 4 / 4 课13 个步骤

memcpy 与 memset 是 CoddyKit 上的免费 C Academy 课时。 这是第 4 节课,共 4 节。 你可以在下方免费阅读本课时的完整内容 — 然后在浏览器中使用内置代码编辑器和全天候 AI 导师进行实践。 这是 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);

它会将 src 中的恰好 n 个字节复制到 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);

它会用字节值 value 填充 ptr 处的 n 个字节。该值会被解释为 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,这对于整数、浮点数和指针来说都是有效的零值。

#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 设置的是每个字节,而不是每个元素。使用它将 int 数组填充为 1,结果不是由 1 组成的数组。

每个 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;)通常表达得更清晰,并且能完成相同的工作。

当通过类型已被擦除的通用 void * 指针进行复制时,通常更适合使用 memcpy。

#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' 处停止。
免费开始

用 AI 导师学习 C — 免费

在浏览器中编写并运行真实代码,获得全天候 AI 导师的即时帮助,并在网页或应用中继续学习。

课程
39
课程
144

常见问题解答

「memcpy 与 memset」课时是免费的吗?

是的 — 「memcpy 与 memset」的完整文本可在网页上免费阅读。要进行交互式练习(内置代码编辑器和全天候 AI 导师)并解锁 C Academy 课程的其余内容,请升级到 CoddyKit PRO。 C Academy 课程共包含 4 节课。

「memcpy 与 memset」这节课中我会学到什么?

原始内存函数 你通过在浏览器中直接运行的动手代码来练习 C Academy,全天候 AI 导师会在你学习这节课的过程中回答你的问题。

学习 C Academy 需要有经验吗?

无需任何先前经验。CoddyKit 上的 C Academy 课程适合初学者到高级学习者,你可以从这里开始或从头开始,按照自己的节奏学习。 这是第 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