【C语言入门级教学】内存函数

文章目录

1.memcpy使⽤和模拟实现

c 复制代码
void * memcpy ( void * destination, const void * source, size_t num );//可以拷贝许多类型的数据,所以数据地址类型是void*

功能

• 从源头指向的内存块拷贝固定字节数的数据到目标指向的内存块

• memcpy:memory copy(内存拷贝)

• 要包含头文件==<string.h>==

• 与strcpy函数不同的点:这个函数在遇到 '\0' 的时候并不会停下来,总是精确地拷贝参数传入的字节数

• 如果source和destination有任何的重叠,复制的结果都是未定义的。

参数

destination:指针,指向目标空间,拷贝的数据存放在这里

source:指针,指向源空间,要拷贝的数据从这里来

num:要拷贝的数据占据的字节数

返回值

函数运行结束后返回拷贝后的目的地内存块的起始地址

c 复制代码
#include<stdio.h>  
#include<string.h>  
int main() 
{ 
	int arr1[] = { 1,2,3,4,5,6,7,8,9,10 }; 
    int arr2[10] = { 0 }; 
    memcpy(arr2, arr1, 20); 
    int i = 0; for (i = 0; i < 10; i++) 
    { 
        printf("%d ", arr2[i]); 
    } 
    return 0;
 }
//或者
int main()
{
    float arr1[]={1.2f,2.2f,3.2f,4.2f,5.5f};
    float arr2[10]={0};
//  memcpy(arr2,arr1,20);
    memcpy(arr2,arr1,5*sizeof(float));//忘记浮点数的字节数可以这样做
    return 0;
}

有个题外话:float型无法精确保存数据

memcpy函数的模拟实现:

c 复制代码
void * memcpy ( void * dest, const void * src, size_t num) 
{ 
    void * ret = dest; 
    assert(dest); 
    assert(src); 
    while (num--) 
    { 
        *(char *)dest = *(char *)src;//转换成char*可以一个字节一个字节赋值,但是是临时转换
        //如果转换为整型,只能四个字节四个字节赋值
        src=(char*)src+1;//需要再重新转换成char*
        dest=(char*)dest+1;
        //不能写成
        //*(char*)dest++=*(char*)src++;
        //因为dest和src会先转换成char*,但是++操作会给dest和src++,而不是给(char*)dest和(char*)src进行++操作
    } 
    return ret; 
}

注意

void*不能进行++操作,因为void *是一个指向未知类型的指针类型,它的大小是不确定的。而++操作需要知道指针所指向的对象的大小,才能正确的进行指针运算。

如果出现下段这种代码:

c 复制代码
#include<stdio.h>  
#include<string.h> 
int main() 
{ 
    int arr1[] = { 1,2,3,4,5,6,7,8,9,10 }; 
    memcpy(arr1+2, arr1, 20); 
    int i = 0; for (i = 0; i < 10; i++) 
    { 
        printf("%d ", arr1[i]); 
    }
    return 0; 
}
//输出结果却是1 2 1 2 1 2 1

分析:因为目标空间和源头空间重复,给arr4拷贝时arr2已经被拷贝为1了,所以arr4会被拷贝现在arr2的值,那怎么解决这个问题呢,可以用memmove函数(但是vs编译器的memcpy可以拷贝重叠空间,属于超额完成任务)

2.memmove使⽤和模拟实现

c 复制代码
void * memmove ( void * destination, const void * source, size_t num );//和memcpy参数一样

功能

• memmove函数也是完成内存拷贝的

• memmove函数处理的源内存块和⽬标内存块是可以重叠,也可以不重叠。

• 需要包含头文件==<string.h>==

参数

destination:指针,指向目标空间,拷贝的数据存放在这里

source:指针,指向源空间,要拷贝的数据从这里来

num:要拷贝的数据占据的字节数

返回值

函数运行结束后,返回目标空间的起始地址

c 复制代码
#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

memmove的模拟实现:

第二种方法

c 复制代码
#include<stdio.h>
#include<assert.h>
void* my_memmove ( void * dest, const void * src, size_t num) 
{ 
    assert(dest&&src);
    void* ret=dest;//先存起来
    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 ret;//与memmove函数保持一致
}
int main() 
{ 
    int arr1[] = { 1,2,3,4,5,6,7,8,9,10 }; 
    my_memmove(arr1+2, arr1, 20); 
    int i = 0; 
    for (i = 0; i < 10; i++) 
    { 
        printf("%d ", arr1[i]); 
    }
    return 0; 
}

第一种方法

c 复制代码
#include<stdio.h>
#include<assert.h>
void * memmove ( void * dest, const void * src, size_t count)
{
    assert(dest&&src);
 	void * ret = dst;
 	if (dest <= src || (char *)dest >= ((char *)src + count)) 
    {
         while (count--) 
         {
             *(char *)dest = *(char *)src;
             dest = (char *)dest + 1;
             src = (char *)src + 1;
         }
     }
     else 
     {
         dest = (char *)dest + count - 1;
         src = (char *)src + count - 1;
         while (count--) 
         {
             *(char *)dest = *(char *)src;
             dest = (char *)dest - 1;
             src = (char *)src - 1;
         }
     }
     return(ret);
}
int main() 
{ 
    int arr1[] = { 1,2,3,4,5,6,7,8,9,10 }; 
    my_memmove(arr1+2, arr1, 20); 
    int i = 0; 
    for (i = 0; i < 10; i++) 
    { 
        printf("%d ", arr1[i]); 
    }
    return 0; 
}

3.memset函数的使⽤和模拟实现

c 复制代码
void * memset ( void * ptr, int value, size_t num ); 

功能

• memset是⽤来设置内存的,将内存中的值以字节为单位设置成想要的内容。

• 需包含头文件==<string.h>==

参数

ptr:指针,指向要设置的内存空间,存放了要设置的内存空间的起始地址

value:要设置的值,函数将会把value值转换成unsigned char的数据进行设置的,也就是以字节为单位来设置内存块的

num:要设置的内存长度,单位是字节

返回值

函数运行完之后返回要设置的内存空间的起始位置

c 复制代码
#include<stdio.h>  
#include<string.h>
int main () 
{ 
    char str[] = "hello world"; 
    memset (str,'x',6); 
    printf(str); 
    return 0; 
}

输出的结果: xxxxxxworld

注意

memset函数对内存单元的设置是以字节为单位的

c 复制代码
int main()
{
    int arr[10]={0};
    memset(arr,1,40);
    return 0;
}

结果如下:发现每个字节都设置为1,而不是00 00 00 01

4.memcmp函数的使⽤和模拟实现

c 复制代码
int memcmp ( const void * ptr1, const void * ptr2, size_t num );

功能

• ⽐较从ptr1和ptr2指针指向的位置开始,向后的num个字节

• 需包含头文件==<string.h>==

参数

ptr1:指针,指向一块待比较的内存块

ptr2:指针,指向另外一块待比较的内存块

num:指定的比较长度,单位是字节

返回值

示例一:

c 复制代码
int main()
{
	int arr1[]={1,2,3,4,5,6,7,8,9,10};
	int arr2[]={1,2,3,4,8};
	int r=memcmp(arr1,arr2,17);
    if(r>0)
    	printf(">\n");
    else if(r<0)
        printf("<\n");
    else
        printf("=\n");
    return 0;
}

示例二:

c 复制代码
#include<stdio.h>  
#include<string.h>
int main() 
{ 
    char buffer1[] = "DWgaOtP12df0"; 
    char buffer2[] = "DWGAOTP12DF0"; 
    int n; n = memcmp(buffer1, buffer2, sizeof(buffer1)); 
    if (n > 0)  
        printf("'%s' is greater than '%s'.\n", buffer1, buffer2); 
    else if (n < 0)  
        printf("'%s' is less than '%s'.\n", buffer1, buffer2); 
    else  
        printf("'%s' is the same as '%s'.\n", buffer1, buffer2); 
    return 0; 
}
相关推荐
地平线开发者4 小时前
profiler debug 工具用法与高一致性策略
算法·自动驾驶
编程大师哥4 小时前
匿名函数 lambda + 高阶函数
java·python·算法
isyangli_blog4 小时前
OpenDayLight (Carbon 版本) 启动与组件安装
开发语言·php
vb2008115 小时前
FastAPI APIRouter
开发语言·python
Benszen5 小时前
KVM虚拟化解决方案
开发语言·perl
会编程的土豆5 小时前
Go 语言反射(Reflection)详解
开发语言·后端·golang
東雪木5 小时前
多线程与并发编程 专属复习笔记
java·开发语言·笔记·java面试
我叫袁小陌5 小时前
算法解题思路指南
算法
地平线开发者5 小时前
Conv+BN+Add+ReLU 融合机制简介
算法·自动驾驶