【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

分析:因为目标空间和源头空间重复,给arr[4]拷贝时arr[2]已经被拷贝为1了,所以arr[4]会被拷贝现在arr[2]的值,那怎么解决这个问题呢,可以用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; 
}
相关推荐
啃啃大瓜2 小时前
python常量变量运算符
开发语言·python·算法
熊文豪3 小时前
【华为OD】找出通过车辆最多颜色
算法·华为od
塔中妖3 小时前
【华为OD】环中最长子串2
算法·华为od
JCBP_3 小时前
QT(3)
开发语言·汇编·c++·qt·算法
秃顶老男孩.3 小时前
web中的循环遍历
开发语言·前端·javascript
研梦非凡3 小时前
ICCV 2025|基于曲线感知高斯溅射的3D参数曲线重建
人工智能·算法·3d
XFF不秃头3 小时前
力扣刷题笔记-三数之和
c++·笔记·算法·leetcode
滴滴滴嘟嘟嘟.3 小时前
Qt信号与槽机制
开发语言·qt
快起来搬砖了3 小时前
实现一个优雅的城市选择器组件 - Uniapp实战
开发语言·javascript·uni-app