C语言内存函数

简介: C语言内存函数

内存函数!!!


c语言中有专门对字符串使用的函数,比如strcpy(字符串拷贝),strcat(字符串追加),strcmp(字符串比较),strstr(在一个字符串中查找另一个字符串)等等,那么c语言不能这么偏心呀,有没有对其它类型可以使用的函数呢?那就要说到我们的内存函数


顾名思义,内存函数可以针对内存中的数据进行一定的小操作,这时候就不管你是什么类型了,

都要给我乖乖听话,我们先简单介绍四个内存函数:

memcpy  memmove   memset   memcmp


1:memcpy


memcpy 的作用是进行数据拷贝,将一个数组的内容拷贝到指定的数组内


void * memcpy ( void * destination, const void * source, size_t num )

memcpy 函数有两个参数 ,destination也就是存放拷贝内容的地址,source是存放初始内容的地址,就是把source地址指向的数据拷贝到destination地址指向的数据中


因为这个函数可以对任意类型的数据使用,所以定义成 void* 类型的指针,num是拷贝数据的大小,单位是字节,定义成size_t类型,memcpy的返回类型是void*,其实细心思考一下就知道为什么返回void*了。

memcpy的使用


#include<stdio.h>
#include<string.h>
int main()
{
    int arr1[10] = { 1,2,3,4,5,6,7,8,9,10 };
    int arr2[10] = { 0 };
    int i = 0;

    memcpy(arr2, arr1, 5 * sizeof(int));
    for (i = 0; i < 10; i++)
    {
        printf("%d ",arr2[i]);
    }
    return 0;
}



可以清晰地看到arr2数组内的值被改变了

温馨提示

 使用内存函数前别忘了加头文件哦(#include<string.h>)

其实我们是可以在arr2中任意位置放入拷贝的数据,也可以拷贝arr1中任意位置的数据,

前提是不能越界访问且一定是连续的



memcpy的模拟实现

#include<stdio.h>

#include<string.h>

#include<assert.h>

void* my_memcpy(char* p1, char* p2, size_t num)

{

void* ret = p1;

assert(p1 && p2);

while (num--)

{

*((char*)p1) = *((char*)p2);

(char*)p1 = (char*)p1 + 1;

(char*)p2 = (char*)p2 + 1;

}

return ret;

}

int main()

{

int arr1[10] = { 1,2,3,4,5,6,7,8,9,10 };

int arr2[10] = { 0 };

my_memcpy(arr2+3, arr1, 20);

int i = 0;

for (i = 0; i < 10; i++)

{

printf("%d ", arr2[i]);

}

return 0;

}


因为memcpy中第三个参数是拷贝数据的大小,单位是字节,所以模拟函数内用char*类型来交换。

2:memmove


那要是拷贝一个数组中的数据,还是放在这个数组中,内存发生重叠怎么办呢?

这就用到memmove函数了,memcpy的差别就是memmove函数处理的源内存块和⽬标内存块是可以重叠的。

memmove的使用

#include<stdio.h>
#include<string.h>
int main()
{
    int arr1[10] = { 1,2,3,4,5,6,7,8,9,10 };
    int i = 0;

    memmove(arr1, arr1+5, 5 * sizeof(int));
    for (i = 0; i < 10; i++)
    {
        printf("%d ",arr1[i]);
    }
    return 0;
}


memmove的模拟实现


void* my_memmove(char* p1, char* p2, size_t num)

{

void* ret = p1;

assert(p1);

assert(p2 );

if (p1 < p2)

{

while (num--)

{

*((char*)p1) = *((char*)p2);

(char*)p1 = (char*)p1 + 1;

(char*)p2 = (char*)p2 + 1;

}

}

else

while (num--)

{

*((char*)p1 + num) = *((char*)p2 + num);

}

return ret;

}

int main()

{

int arr1[10] = { 1,2,3,4,5,6,7,8,9,10 };

int arr2[10] = { 0 };

my_memmove(arr1, arr1+5, 20);

int i = 0;

for (i = 0; i < 10; i++)

{

printf("%d ", arr1[i]);

}

return 0;

}

memcpy相比,只是多了内存重叠的数据拷贝,

有两种情况:



第一种方式就是memcpy的拷贝方式,这里不再多说;

第二种方式是从后往前拷贝,可以看一下代码实现方式:


while (num--)

{

*((char*)p1 + num) = *((char*)p2 + num);

}


p1+num,从最后的地址开始拷贝,然后 num--, num=0 while 循环结束。

3:memset


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

void * memset ( void * ptr, int value, size_t num );


第二个参数表示要设置的值,以int 形式传递, 如果值超过了无符号char的最大值,就会把该值转换成无符号char能存的下的值再写到内存里,


希望大家能够理解,例如

300无符号char类型中存放的是44,

例如:

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

输出结果:


xxxxxxworld


4:memcmp


int memcmp ( const void * ptr1, const void * ptr2, size_t num );


这个就很好理解了,比较两个数据的大小

假设有两个数组:arr1,arr2;


<0 arr1<arr2
0 arr1=arr2
>0 arr1>arr2


例子:

#include <stdio.h>
#include <string.h>
int main()
{
    char arr1[] = "abcdefg";
    char arr2[] = "abcdefh";
    int n;
    n = memcmp(arr1,arr2, sizeof(arr1));
    if (n > 0)
        printf("大于\n");
    else if (n < 0)
        printf("小于\n");
    else
        printf("等于\n");
    return 0;
}


运行结果:



把字符串换成整形也是可以的



结语


这里四个函数也介绍完了,希望给你们带来帮助!

(草草结语,实在是内心烦躁,看完的话点个赞吧)

相关文章
|
安全 C语言 C++
比较C++的内存分配与管理方式new/delete与C语言中的malloc/realloc/calloc/free。
在实用性方面,C++的内存管理方式提供了面向对象的特性,它是处理构造和析构、需要类型安全和异常处理的首选方案。而C语言的内存管理函数适用于简单的内存分配,例如分配原始内存块或复杂性较低的数据结构,没有构造和析构的要求。当从C迁移到C++,或在C++中使用C代码时,了解两种内存管理方式的差异非常重要。
448 26
|
11月前
|
存储 C语言
`scanf`是C语言中用于按格式读取标准输入的函数
`scanf`是C语言中用于按格式读取标准输入的函数,通过格式字符串解析输入并存入指定变量。需注意输入格式严格匹配,并建议检查返回值以确保读取成功,提升程序健壮性。
1595 0
|
安全 C语言
C语言中的字符、字符串及内存操作函数详细讲解
通过这些函数的正确使用,可以有效管理字符串和内存操作,它们是C语言编程中不可或缺的工具。
556 15
|
人工智能 Java 程序员
一文彻底搞清楚C语言的函数
本文介绍C语言函数:函数是程序模块化的工具,由函数头和函数体组成,涵盖定义、调用、参数传递及声明等内容。值传递确保实参不受影响,函数声明增强代码可读性。君志所向,一往无前!
720 1
一文彻底搞清楚C语言的函数
|
C语言
【C语言程序设计——函数】亲密数判定(头歌实践教学平台习题)【合集】
本文介绍了通过编程实现打印3000以内的全部亲密数的任务。主要内容包括: 1. **任务描述**:实现函数打印3000以内的全部亲密数。 2. **相关知识**: - 循环控制和跳转语句(for、while循环,break、continue语句)的使用。 - 亲密数的概念及历史背景。 - 判断亲密数的方法:计算数A的因子和存于B,再计算B的因子和存于sum,最后比较sum与A是否相等。 3. **编程要求**:根据提示在指定区域内补充代码。 4. **测试说明**:平台对代码进行测试,预期输出如220和284是一组亲密数。 5. **通关代码**:提供了完整的C语言代码实现
456 24
|
存储 C语言
【C语言程序设计——函数】递归求斐波那契数列的前n项(头歌实践教学平台习题)【合集】
本关任务是编写递归函数求斐波那契数列的前n项。主要内容包括: 1. **递归的概念**:递归是一种函数直接或间接调用自身的编程技巧,通过“俄罗斯套娃”的方式解决问题。 2. **边界条件的确定**:边界条件是递归停止的条件,确保递归不会无限进行。例如,计算阶乘时,当n为0或1时返回1。 3. **循环控制与跳转语句**:介绍`for`、`while`循环及`break`、`continue`语句的使用方法。 编程要求是在右侧编辑器Begin--End之间补充代码,测试输入分别为3和5,预期输出为斐波那契数列的前几项。通关代码已给出,需确保正确实现递归逻辑并处理好边界条件,以避免栈溢出或结果
911 16
|
存储 编译器 C语言
【C语言程序设计——函数】分数数列求和2(头歌实践教学平台习题)【合集】
函数首部:按照 C 语言语法,函数的定义首部表明这是一个自定义函数,函数名为fun,它接收一个整型参数n,用于指定要求阶乘的那个数,并且函数的返回值类型为float(在实际中如果阶乘结果数值较大,用float可能会有精度损失,也可以考虑使用double等更合适的数据类型,这里以float为例)。例如:// 函数体代码将放在这里函数体内部变量定义:在函数体中,首先需要定义一些变量来辅助完成阶乘的计算。比如需要定义一个变量(通常为float或double类型,这里假设用float。
804 3
|
存储 算法 安全
【C语言程序设计——函数】分数数列求和1(头歌实践教学平台习题)【合集】
if 语句是最基础的形式,当条件为真时执行其内部的语句块;switch 语句则适用于针对一个表达式的多个固定值进行判断,根据表达式的值与各个 case 后的常量值匹配情况,执行相应 case 分支下的语句,直到遇到 break 语句跳出 switch 结构,若没有匹配值则执行 default 分支(可选)。例如,在判断一个数是否大于 10 的场景中,条件表达式为 “num> 10”,这里的 “num” 是程序中的变量,通过比较其值与 10 的大小关系来确定条件的真假。常量的值必须是唯一的,且在同一个。
1018 2
|
存储 编译器 C语言
【C语言程序设计——函数】回文数判定(头歌实践教学平台习题)【合集】
算术运算于 C 语言仿若精密 “齿轮组”,驱动着数值处理流程。编写函数求区间[100,500]中所有的回文数,要求每行打印10个数。根据提示在右侧编辑器Begin--End之间的区域内补充必要的代码。如果操作数是浮点数,在 C 语言中是不允许直接进行。的结果是 -1,因为 -7 除以 3 商为 -2,余数为 -1;注意:每一个数据输出格式为 printf("%4d", i);的结果是 1,因为 7 除以 -3 商为 -2,余数为 1。取余运算要求两个操作数必须是整数类型,包括。开始你的任务吧,祝你成功!
871 1