当前位置:网站首页>C语言-内存操作函数
C语言-内存操作函数
2022-08-11 05:30:00 【CHAKMING1】
目录
一、内存函数详解
1.memcpy函数
为什么会有memcpy函数呢,这个函数与strcpy有什么区别,首先strcpy是字符串操作函数,那么我们如果想对整型、浮点型以及我们自己自定义的数据类型要如何操作,这时候就可以使用memcpy函数。
void * memcpy ( void * destination, const void * source, size_t num );上面是函数的格式,void*类型是可以返回任意类型的指针。
destination:是接受要复制的内容的一个指针,同样是void*类型的
source:是要复制过去的来源指针,这里加上const是因为防止source被修改
num:复制的字节数,size_t是一个无符号类型
这个函数本质上是可以接受任何的指针类型,所以使用了void*来当作一个“万能”的作用,再通过类型转换,而转换成实际我们想要的指针类型。
void* my_memcpy(void* dest, const void* src, size_t num)
{
assert(dest && src); // 进行断言,需要包含头文件assert.h
void* ret = dest; // 定义一个ret接受dest,防止dest直接被修改无法返回
while (num--)
{
// 实际我们在传输过程中,无论是任何的数据类型,我们都是一个字节一个字节传
// 因为需要转换成char*类型,这样每次指针移动都是移动一位
*(char*)dest = *(char*)src;
dest = (char*)dest + 1;
src = (char*)src + 1;
}
return ret;
}
以上就是memcpy函数的内部实现,那么下面这段代码是否有问题?
int main()
{
int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };
my_memcpy(arr + 2, arr, sizeof(int)*5);
for (int i = 0; i < 10; i++) {
printf("%d ", arr[i]);
}
printf("\n");
}我们预想的结果可能是1,2,1,2,3,4,5,8,9,10,但实际并不是这样的。

实际输出的效果是这样,因为这个函数是没办法对有重复的内存区域进行复制的,因为我们在复制过程中,到第三位的时候,这个值以及被改掉了,所以之后的数一直复制的都是1,2,这就导致了这个值不是我们想要的。但实际,用库函数中的memcpy不会发生这种情况,因为编译器已经预料到我们会这样操作,所以现在有些编译器中memcpy函数也可以对这种情况进行操作,但是不建议这么做。
所以为了解决重叠拷贝的问题就有了memmove这个函数
2.memmove函数
memmove函数是在memcpy函数的基础上,可以对有重复包含的内存区域进行复制,得到我们想要的结果。
void * memmove ( void * destination, const void * source, size_t num );这是memmove函数的格式,与memcpy函数一致,这里不做详细解释。
那么,这个函数是如何实现的?
void *my_memmove(void *dest, const void *src, size_t count)
{
assert(dest && src);
void *ret = dest;
// dest 为低地址,就从前向后拷贝
if (dest < src)
{
while (count)
{
*(char *)dest = *(char *)src;
dest = (char *)dest + 1;
src = (char *)src + 1;
count--;
}
}
// dest 为高地址,就从后向前拷贝
else
{
while (count--)
{
*((char *)dest + count) = *((char *)src + count);
}
}
return ret;
}本质上,这个函数其实内部进行复制的过程与memcpy函数一致,但有一个不同的地方在于,如果说目标地址要比源头地址高,我们就从后向前进行拷贝,如果是目标地址比源头地址低,则还是按照memcpy函数的拷贝方式。

这样,我们就能得到想要的结果。
3.memcmp函数
这个函数是一个内存比较函数,比较两个指针开始的num字节大小,返回值与strcmp一致。
int memcmp ( const void * ptr1, const void * ptr2, size_t num );比较ptr1和ptr2指针开始的num个字节,返回值是int类型,返回值如下:

从第一个字节开始比较,如果ptr1大于ptr2,则直接返回一个大于0的数,ptr1等于ptr2,则继续往后比较,这时候num--,直到num等于0,两个指针还是相等,则返回一个0,ptr1小于ptr2,则直接返回一个小于0的数字。
int my_memcmp(const void* ptr1, const void* ptr2, size_t count)
{
assert(ptr1 && ptr2);
// 因为在while循环就进行了比较,所以要先--
while (--count && *(char*)ptr1 == *(char*)ptr2) // 这里是遇到不同后,退出
{
((char*)ptr1)++;
((char*)ptr2)++;
}
return *(char*)ptr1 - *(char*)ptr2; // 直接返回两个指针对应的值的差值
}4.memset函数
void * memset ( void * ptr, int value, size_t num );这是一个内存设置函数,ptr是需要被设置的指针,value是设置的值,num是从开始地址的num个字节,设置为value值。
#include <stdio.h>
#include <string.h>
int main ()
{
char str[] = "almost every programmer should know memset!";
memset (str,'-',6);
puts (str);
return 0;
}输出结果:------ every programmer should know memset
边栏推荐
猜你喜欢

将一个excel文件中多个sheet页“拆分“成多个“独立“excel文件

JNI入门

开发公众号授权遇到的redirect_uri参数错误

USB URB

场景驱动的特征计算方式OpenMLDB,高效实现“现算先用”

Jetpack's dataBinding

开源机器学习数据库OpenMLDB贡献者计划全面启动

The official website of OpenMLDB is upgraded, and the mysterious contributor map will take you to advance quickly

Day 79

Fourth Paradigm OpenMLDB optimization innovation paper was accepted by VLDB, the top international database association
随机推荐
OpenMLDB Pulsar Connector:高效打通实时数据到特征工程
第六届蓝帽杯 EscapeShellcode
【无标题】
2021年vscode终端设置为bash模式
JS case exercise (classic case of teacher pink)
The whole process of Tinker access --- configuration
微信小程序_开发工具的安装
Day 78
The mount command - mounted read-only, solution
第一章 Verilog语言和Vivado初步使用
Day 80
活动预告 | 4月23日,多场OpenMLDB精彩分享来袭,不负周末好时光
Open Source Machine Learning Database OpenMLDB Contributor Program Fully Launched
The third phase of the contributor task is wonderful
Day 67
C语言实现简易扫雷(附带源码)
Asis2016 books null off by one
厂商推送平台-华为接入
Event Preview | On April 23, a number of wonderful sharing sessions of OpenMLDB will come, which will live up to the good time of the weekend
stack stack