C语⾔内存函数
1. memcpy 使⽤和模拟实现
声明
下面是 memcpy() 函数的声明。
void *memcpy(void *str1, const void *str2, size_t n)
参数
str1 -- 指向用于存储复制内容的目标数组,类型强制转换为 void* 指针。
str2 -- 指向要复制的数据源,类型强制转换为 void* 指针。
n -- 要被复制的字节数。
注意点
1 这个函数在遇到 '\0' 的时候并不会停下来。所以可能会拷贝越界
2 如果source和destination指向的空间有任何的重叠,复制的结果都是未定义的。
返回值
该函数返回一个指向目标存储区 str1 的指针。
实例
// 将字符串复制到数组 dest 中
#include <stdio.h>
#include <string.h>
int main ()
{
const char src[50] = "http://www.runoob.com";
char dest[50];
//拷贝时的长度不要超过原来数据的长度尽量
//两个拷贝的空间上不要出现重叠
memcpy(dest, src, strlen(src)+1);
printf("dest = %s\n", dest);
return(0);
}
模拟实现:
void * memcpy ( void * dst, const void * src, size_t count)
{
void * ret = dst;
assert(dst);
assert(src);
/*
* copy from lower addresses to higher addresses
*/
//按字节拷贝即可
while (count--) {
*(char *)dst = *(char *)src;
dst = (char *)dst + 1;
src = (char *)src + 1;
}
return(ret);
}
2 memmove使⽤
void * memmove ( void * destination, const void * source, size_t num );
• 和memcpy的差别就是memmove函数处理的源内存块和⽬标内存块是可以重叠的。
• 如果源空间和⽬标空间出现重叠,就得使⽤memmove函数处理。
#include <stdio.h>
#include <string.h>
int main()
{
int arr1[] = { 1,2,3,4,5,6,7,8,9,10 };
memmove(arr1+2, arr1, 20);
int i = 0;
for (i = 0; i < 10; i++)
{
printf("%d ", arr1[i]);
}
return 0;
}
//输出结果
1 2 1 2 3 4 5 8 9 10
/*
1 原始数组:
arr1[] = {1,2,3,4,5,6,7,8,9,10}
2
memmove(arr1 + 2, arr1, 20)参数解析:
目标地址:arr1 + 2(即从第3个元素开始的位置)
源地址:arr1(数组起始位置)
字节数:20(即5个int,假设int为4字节)
拷贝过程:
先将源内存块(前5个元素)复制到临时缓冲区:
临时缓冲区得到:{1,2,3,4,5}
然后将临时缓冲区内容复制到目标位置:
从arr1[2]开始覆盖,变成:{1,2,1,2,3,4,5,8,9,10}
关键点:
memmove允许源和目标内存区域重叠
它会先复制源数据到临时空间,再复制到目标位置
这里拷贝的是前5个元素(20字节)到第3个元素开始的位置
*/
memmove模拟实现:
void * memmove ( void * dst, const void * src, size_t count)
{
void * ret = dst;
if (dst <= src || (char *)dst >= ((char *)src + count)) {
/*
* Non-Overlapping Buffers
* copy from lower addresses to higher addresses
*/
//如果目标地址小于等于源地址或者和源地址没有重叠的区域
//那么不用担心源地址的数据被覆盖
while (count--) {
*(char *)dst = *(char *)src;
dst = (char *)dst + 1;
src = (char *)src + 1;
}
}
else {
/*
* Overlapping Buffers
* copy from higher addresses to lower addresses
*/
//从后往前复制不用担心源数据被提前覆盖
dst = (char *)dst + count - 1;
src = (char *)src + count - 1;
while (count--) {
*(char *)dst = *(char *)src;
dst = (char *)dst - 1;
src = (char *)src - 1;
}
}
return(ret);
}
3 memset函数的使⽤
void * memset ( void * ptr, int value, size_t num );
memset() 函数将指定的值 c 复制到 str 所指向的内存区域的前 n 个字节中,这可以用于将内存块清零或设置为特定值。在一些情况下,需要快速初始化大块内存为零或者特定值,memset() 可以提供高效的实现。在清空内存区域或者为内存区域赋值时,memset() 是一个常用的工具函数。
参数
str -- 指向要填充的内存区域的指针。
c -- 要设置的值,通常是一个无符号字符(值大小为0-255)。把每个字节的值设置为c
n -- 要被设置为该值的字节数。
返回值
该值返回一个指向存储区 str 的指针。
注意事项
memset()
并不对指针ptr
指向的内存区域做边界检查,因此使用时需要确保ptr
指向的内存区域足够大,避免发生越界访问。memset()
的第二个参数value
通常是一个int
类型的值,但实际上只使用了该值的低8位。这意味着在范围0
到255
之外的其他值可能会产生未定义的行为。num
参数表示要设置的字节数,通常是通过sizeof()
或其他手段计算得到的。
实例
#include <stdio.h>
#include <string.h>
int main ()
{
char str[50];
strcpy(str,"This is string.h library function");
puts(str);
memset(str,'$',7);
puts(str);
return(0);
}
让我们编译并运行上面的程序,这将产生以下结果:
This is string.h library function
$$$$$$$ string.h library function
4memcmp函数的使⽤
• ⽐较从ptr1和ptr2指针指向的位置开始,向后的num个字节即按字节(char类型)比较大小 • 返回值如下:
返回值
如果返回值 < 0,则表示 str1 小于 str2。
如果返回值 > 0,则表示 str1 大于 str2。
如果返回值 = 0,则表示 str1 等于 str2