memcpy 与 memset
原始内存函数
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 反馈 — 无需本地设置。
此课程中的所有课时
- strlen、strcpy、strcat
- strcmp 与比较
- strtok 与分词
- memcpy 与 memset