C语言内存函数详解:memcpy、memmove、memset与memcmp使用指南
原文地址: https://88box.top 生成时间: 2026-05-21 01:00:56
C语言内存函数 - hey99 知识搜索引擎
精选文章
C语言内存函数
C语言内存函数
更新于 2026-05-20 16:57
restful
c语言
后端
开发语言
目录
- memcpy
1.1 代码演示
1.2 模拟实现
- memmove
2.1 代码演示
2.2 模拟实现
- memset
3.1 代码演示
3.2 总结
- memcmp
4.1 代码演示
4.2 总结
- memcpy
项目
内容
函数名
memcpy
头文件
include
函数原型
void memcpy(void destination, const void *source, size_t num);
功能
从
source
指向的内存位置开始,复制
num
个字节的数据到
destination
指向的内存位置
参数
destination
目标空间地址,拷贝后的数据存放到这里
参数
source
源空间地址,要被拷贝的数据从这里开始
参数
num
要拷贝的数据字节数
返回值
返回目标空间的起始地址,即
destination
注意事项
memcpy
只负责按字节拷贝内存
,
不关心数据类型
限制条件
如果
source
和
destination
指向的内存区域发生重叠,结果是
未定义的
1.1 代码演示
字符拷贝:
define
_CRT_SECURE_NO_WARNINGS
1
include
include
int
main
(
)
{
char
arr
[
20
]
=
{
0
}
;
char
arr1
[
]
=
"abcdef"
;
memcpy
(
arr
,
arr1
,
6
)
;
printf
(
"%s\n"
,
arr1
)
;
//abcdef
return
0
;
}
数字拷贝
int
main
(
)
{
int
arr1
[
10
]
=
{
0
}
;
int
arr2
[
]
=
{
1
,
2
,
3
,
4
,
5
,
6
,
7
,
8
,
9
,
10
}
;
int
sz
=
sizeof
(
arr2
)
/
sizeof
(
arr2
[
0
]
)
;
memcpy
(
arr1
,
arr2
,
sz
*
4
)
;
for
(
int
i
=
0
;
i
<
sz
;
i
++
)
printf
(
"%d "
,
arr1
[
i
]
)
;
// 1 2 3 4 5 6 7 8 9 10
return
0
;
}
画图演示:
注意:在拷贝中可能会出现重叠的情况,如下:
int
main
(
)
{
int
arr1
[
10
]
=
{
0
}
;
int
arr2
[
]
=
{
1
,
2
,
3
,
4
,
5
,
6
,
7
,
8
,
9
,
10
}
;
int
sz
=
sizeof
(
arr2
)
/
sizeof
(
arr2
[
0
]
)
;
memcpy
(
arr2
,
arr2
+
2
,
20
)
;
//源:arr2[2] ~ arr2[6]
//目标:arr2[0] ~ arr2[4]
for
(
int
i
=
0
;
i
<
sz
;
i
++
)
printf
(
"%d "
,
arr2
[
i
]
)
;
// 3 4 5 6 7 6 7 8 9 10
return
0
;
}
这是
从后往前
进行拷贝的,拷贝结果和预期效果一样(但不一定是对的,是依赖编译器的实现方式和效果),但是
arr2
和
arr2 + 2
属于同一个数组,源区域和目标区域发生
重叠
,使用
memcpy
会导致
未定义行为
,我们再来看
从前往后拷贝
的情况:
下面列出在下面的情况下不能使用
memcpy
函数:
不能使用 memcpy 的情况
原因
正确做法
源内存和目标内存发生
重叠
memcpy
不保证重叠拷贝的正确性,会导致未定义行为
使用
memmove
源指针或目标指针是
空指针
memcpy
会访问非法内存,程序可能崩溃
拷贝前判断指针是否为
NULL
拷贝长度
超过源内存大小
会读取越界内存,导致未定义行为
确保拷贝字节数不超过源空间大小
拷贝长度超过
目标内存大小
会写入越界内存,可能破坏其他数据
确保目标空间足够大
拷贝的字节数
写死为固定数字
不同平台上数据类型大小可能不同,容易出错
使用
sizeof
计算拷贝大小
目标内存是
只读区域
向只读内存写入会导致程序崩溃
确保目标区域可写
1.2 模拟实现
include
include
include
void
*
my_memcpy
(
void
*
dest
,
const
void
*
src
,
size_t
num
)
//用const来修饰src,代表源头数据中的值不能被修改
{
void
*
p
=
dest
;
//存储目标空间的起始地址
assert
(
dest
&&
src
)
;
//断言dest和src不为空
while
(
num
--
)
{
*
(
(
char
*
)
dest
)
=
*
(
(
char
*
)
src
)
;
dest
=
(
char
*
)
dest
+
1
;
src
=
(
char
*
)
src
+
1
;
}
return
p
;
}
int
main
(
)
{
int
arr1
[
10
]
=
{
0
}
;
int
arr2
[
]
=
{
1
,
2
,
3
,
4
,
5
,
6
,
7
,
8
,
9
,
10
}
;
int
sz
=
sizeof
(
arr1
)
/
sizeof
(
arr1
[
0
]
)
;
//使用sizeof(arr2[0])来表示要拷贝的字节数便于代码的可移植性
my_memcpy
(
arr1
,
arr2
,
3
*
sizeof
(
arr2
[
0
]
)
)
;
for
(
int
i
=
0
;
i
<
sz
;
i
++
)
printf
(
"%d "
,
arr1
[
i
]
)
;
return
0
;
}
画图演示:
- memmove
项目
内容
函数名
memmove
头文件
include
函数原型
void memmove(void destination, const void *source, size_t num);
功能
从
source
指向的内存位置开始,复制
num
个字节的数据到
destination
指向的内存位置
参数
destination
目标空间地址,拷贝后的数据存放到这里
参数
source
源空间地址,要拷贝的数据从这里开始
参数
num
要拷贝的数据所占的字节数
返回值
返回目标空间的起始地址,即
destination
重要特点
memmove
可以处理源内存块和目标内存块重叠的情况
与
memcpy
的区别
memcpy
不适合处理重叠内存,而
memmove
可以正确处理重叠内存
2.1 代码演示
include
include
int
main
(
)
{
int
arr1
[
10
]
=
{
0
}
;
int
arr2
[
]
=
{
1
,
2
,
3
,
4
,
5
,
6
,
7
,
8
,
9
,
10
}
;
int
sz
=
sizeof
(
arr2
)
/
sizeof
(
arr2
[
0
]
)
;
memmove
(
arr1
,
arr2
,
4
*
sizeof
(
arr2
[
0
]
)
)
;
for
(
int
i
=
0
;
i
<
sz
;
i
++
)
printf
(
"%d "
,
arr1
[
i
]
)
;
//1 2 3 4 0 0 0 0 0 0
return
0
;
}
2.2 模拟实现
include
include
include
void
*
my_memmove
(
void
*
dest
,
const
void
*
src
,
size_t
num
)
{
void
*
p
=
dest
;
// 保存目标空间的起始地址,最后用于返回
assert
(
dest
&&
src
)
;
if
(
dest
<
src
)
// 如果目标地址在源地址之前,从前往后拷贝
{
//前->后
while
(
num
--
)
{
*
(
char
*
)
dest
=
*
(
char
*
)
src
;
dest
=
(
char
*
)
dest
+
1
;
src
=
(
char
*
)
src
+
1
;
}
}
else
{
//后->前
while
(
num
--
)
// 如果目标地址在源地址之后,从后往前拷贝
{
*
(
(
char
*
)
dest
+
num
)
=
*
(
(
char
*
)
src
+
num
)
;
}
}
return
p
;
}
int
main
(
)
{
int
arr1
[
10
]
=
{
0
}
;
int
arr2
[
]
=
{
1
,
2
,
3
,
4
,
5
,
6
,
7
,
8
,
9
,
10
}
;
int
sz
=
sizeof
(
arr1
)
/
sizeof
(
arr1
[
0
]
)
;
my_memmove
(
arr2
+
3
,
arr2
,
4
*
sizeof
(
arr2
[
0
]
)
)
;
for
(
int
i
=
0
;
i
<
sz
;
i
++
)
printf
(
"%d "
,
arr2
[
i
]
)
;
//1 2 3 1 2 3 4 8 9 0
return
0
;
}
画图演示:
从后向前的例子:(上述代码的模拟实现)
从前向后的例子:
- memset
项目
内容
函数名
memset
头文件
include
函数原型
void memset(void ptr, int value, size_t num);
功能
从
ptr
指向的内存位置开始,将连续
num
个字节的空间设置为指定的值
参数
ptr
指针,指向要设置的内存空间,也就是目标内存空间的起始地址
参数
value
要设置的值,函数会将
value
转换为
unsigned char
类型后进行设置
参数
num
要设置的内存长度,单位是字节
返回值
返回目标内存空间的起始地址,即
ptr
重要特点
memset
是按
字节设置内存内容的
,不是按
数据类型逐个赋值
注意事项
可以安全地把内存设置为
0
,但不能随意用它把
int
数组设置为
1
、
2
等非零整数
3.1 代码演示
include
include
int
main
(
)
{
char
str
[
]
=
"abcdef"
;
memset
(
str
,
'x'
,
6
)
;
printf
(
"%s\n"
,
str
)
;
//xxxxxx
return
0
;
}
3.2 总结
当有⼀块内存空间需要设置内容的时候,就可以使⽤
memset
函数,值得注意的是
memset
函数对内存单元的设置是
以字节为单位
的。
注意,不能随意用它把
int
数组设置为非零整数,结果会有问题
:
- memcmp
项目
内容
函数名
memcmp
头文件
include
函数原型
int memcmp(const void ptr1, const void ptr2, size_t num);
功能
从
ptr1
和
ptr2
指向的内存位置开始,比较连续
num
个字节的内容
参数
ptr1
指针,指向第一块要比较的内存空间
参数
ptr2
指针,指向第二块要比较的内存空间
参数
num
要比较的字节数
返回值
< 0
第一处不同字节中,
ptr1
指向的
字节值
小于
ptr2
指向的
字节值
返回值
= 0
两块内存在前
num
个字节内完全相同
返回值
0
第一处不同字节中,
ptr1
指向的字节值大于
ptr2
指向的字节值
重要特点
memcmp
是按
字节比较内存内容
,
不是按数据类型整体比较
4.1 代码演示
int
main
(
)
{
int
arr1
[
]
=
{
1
,
2
,
3
,
4
,
5
}
;
// 04 00 00 00
int
arr2
[
]
=
{
1
,
2
,
3
,
1
,
5
}
;
// 01 00 00 00
int
r
=
memcmp
(
arr1
,
arr2
,
5
*
sizeof
(
arr1
[
0
]
)
)
;
printf
(
"%d\n"
,
r
)
;
//1
return
0
;
}
画图演示:
4.2 总结
memcmp
是一个按字节比较两块内存内容的函数,可以指定比较长度,并通过返回值表示大小关系。
memcmp
函数在比较int数组的时候,
memcmp
是按字节进行比较,不是按int数值进行比较
。
完
查看原文
🏷 标签: C语言, 内存操作, 标准库函数