C/C++字符函数和字符串函数详解————内存函数详解与模拟

简介: C/C++字符函数和字符串函数详解————内存函数详解与模拟

1.前言

          前面学习了关于长度受限制的字符串函数和长度不受限制的字符串函数,其中strcmp对应strncmp函数,strcpy函数对应strncpy函数,strcat函数对应strncat函数,今天我们主要了解的是四个内存函数他们分别是memcpy函数,memmove函数,memset函数,memcmp函数。其中memcpy函数和strcpy函数的功能类似,memcmp函数和strcmp函数类似,接下来就让我们感受一下这些函数的魅力吧。

2 .memcpy函数

       对于memcpy函数,有很多人都是第一次接触到,我们进入cplusplus网站cplusplus进行查看memcpy函数的参数。

       我们看到函数的参数是void * destination, const void * source, size_t num,对于参数我们需要知道这个函数是有什么功能,它主要就是对任何类型的数据进行拷贝,所以destination和source都是void*类型,因为void*类型可任盛放任何类型的指针,其中destination是指向目标的指针,source是指向来源的指针,num是想要拷贝几个字节,接下来进行代码演示,代码如下:

#include<stdio.h>
#include <string.h>
int main()
{
  int arr1[10] = { 0 };
  int arr2[5] = { 2,3,4,5,6 };
  memcpy(arr1, arr2, 20);
  int i;
  for (i = 0; i < 10; i++)
  {
    printf("%d ", arr1[i]);
  }
  return 0;
}

我么运行代码,结果如下:

接下来进行函数的模拟

#include<stdio.h>
#include <string.h>
void* my_memcpy(void* str1, const void* str2, size_t num)
{
  char* p = (char*)str1;
  while (num--)
  {
    *(char*)str1 = *(char*)str2;
    str1 = (char*)str1 + 1;
    str2 = (char*)str2 + 1;
  }
  return p;
}
int main()
{
  int arr1[10] = { 0 };
  int arr2[5] = { 2,3,4,5,6 };
  my_memcpy(arr1, arr2, 20);
  int i;
  for (i = 0; i < 10; i++)
  {
    printf("%d ", arr1[i]);
  }
  return 0;
}

       在这里我们需要进行强制转化,转化为char*类型然后一个字节一个字节进行修改,但是这个函数有一定的局限性,当它的目的指针和来源指针指向同一数据且有有重叠部分时函数会出现与预期不同的结果,我们可以简单画一下:

当我们想要把str1拷贝到str2上时当我们拷贝了前三个数据,str1和原来的str2重合时

        想要再次进行修改就会出现 重复拷贝,根据c语言的标准memcpy函数是对来自不同数据的进行拷贝,但是对于来自同一数组的需要用另外的一个函数,此函数就是memmove函数接下来我们介绍memmove函数。

3.memmove函数

       我们同样进入cplusplus网站查看memmove函数的参数,以及功能

          我们看到函数的参数是void * destination, const void * source, size_t num,memmove函数的功能和memcpy函数的功能类似 ,只是memmove是对于来自同一数组的数据进行拷贝,destination和source都是void*类型,因为void*类型可任盛放任何类型的指针,其中destination是指向目标的指针,source是指向来源的指针,num是想要拷贝几个字节,接下来进行代码演示,代码如下:

#include <stdio.h>
#include <string.h>
int main()
{
  int arr[10] = { 0,1,2,3,4,5,6,7,8,9};
  memmove(arr, arr + 3, 20);
  int i;
  for (i = 0; i < 10; i++)
  {
    printf("%d ", arr[i]);
  }
  return 0;
}

运行结果如下:

接下啦我们进行memmove函数的模拟实现,代码如下:

#include <stdio.h>
#include <string.h>
#include <assert.h>
void my_memmove(void* str1, const void* str2, size_t sz)
{
  assert(str1 && str2);
  if (str1 < str2)
  {
    while (sz--)
    {
      *(char*)str1 = *(char*)str2;
      str1 = (char*)str1 + 1;
      str2 = (char*)str2 + 1;
    }
  }
  else
  {
    while (sz--)
    {
      *((char*)str1 + sz) = *((char*)str2 + sz);
    }
  }
}
int main()
{
  int arr[10] = { 0,1,2,3,4,5,6,7,8,9 };
  my_memmove(arr+3, arr , 20);
  int i;
  for (i = 0; i < 10; i++)
  {
    printf("%d ", arr[i]);
  }
  return 0;
}

在这里我们需要看两种情况,第一种是str1在str2前面

这种情况我们只需从前往后进行赋值即可。对于第二种

str1在str2的后面我们不能从前向后进行拷贝,否则就会出现重复赋值,出现错误,这时我们只需要从后往前进行赋值就可以解决。

4.memset函数

        我们进入cplusplus网站进行查阅

       memset函数是对数据进行初始化的函数,这个数据可以是任意类型,但是字符串比较适用,ptr是指向想要修改的位置,value是想要修改为什么值,num是修改几个字节,我们直接进入代码演示,代码如下:

#include <stdio.h>
#include<string.h>
int main()
{
  char arr[] = "abcdefg";
  memset(arr, 'x', 4);
  printf("%s", arr);
  return 0;
}

运行结果如下:

接下来进入我们模拟实现,代码如下:

#include <stdio.h>
#include<string.h>
#include <assert.h>
void* my_memset(void* str, int vaul, size_t sz)
{
  assert(str);
  char* p = (char*)str;
  while (sz--)
  {
    *(char*)str = vaul;
    str = (char*)str + 1;
  }
  return p;
}
int main()
{
  char arr[] = "abcdefg";
  my_memset(arr, 'x', 4);
  printf("%s", arr);
  return 0;
}

5.memcmp函数

       我们进入cplusplus网站查看函数的参数

       memcmp函数的功能就是比较数据的大小,其中num是需要比较的数据的字节数,功能和strncmp类似,我们直接上代码:

 

#include <stdio.h>
#include <string.h>
int main()
{
  int arr[5] = { 0,1,2,3,4 };
  int arr1[5] = { 0 };
  int ret = memcmp(arr, arr1, 5);
  printf("%d", ret);
  return 0;
}

我们可以理解为

前4个字节相同,第五个字节str1大于str2故返回1。运行结果如下;

接下来进行memcmp函数的模拟实现,代码如下:

#include <stdio.h>
#include <string.h>
#include <assert.h>
int my_memcmp(const void* str1, const void* str2, size_t sz)
{
  assert(str1 && str2);
  int i;
  for (i = 0; i < sz; i++)
  {
    if (*(char*)str1 >*(char*)str2)
    {
      return 1;
    }
    else if (*(char*)str1 < *(char*)str2)
    {
      return -1;
    }
    str1 = (char*)str1 + 1;
    str2 = (char*)str2 + 1;
  }
  return 0;
}
int main()
{
  int arr[5] = { 0,1,2,3,4 };
  int arr1[5] = { 0 };
  int ret = my_memcmp(arr, arr1, 5);
  printf("%d", ret);
  return 0;
}

今天的内容就结束了,希望大家可以学到一些东西。

目录
相关文章
|
安全 C语言
C语言中的字符、字符串及内存操作函数详细讲解
通过这些函数的正确使用,可以有效管理字符串和内存操作,它们是C语言编程中不可或缺的工具。
558 15
|
人工智能 机器人 编译器
c++模板初阶----函数模板与类模板
class 类模板名private://类内成员声明class Apublic:A(T val):a(val){}private:T a;return 0;运行结果:注意:类模板中的成员函数若是放在类外定义时,需要加模板参数列表。return 0;
341 0
|
安全 C++
【c++】继承(继承的定义格式、赋值兼容转换、多继承、派生类默认成员函数规则、继承与友元、继承与静态成员)
本文深入探讨了C++中的继承机制,作为面向对象编程(OOP)的核心特性之一。继承通过允许派生类扩展基类的属性和方法,极大促进了代码复用,增强了代码的可维护性和可扩展性。文章详细介绍了继承的基本概念、定义格式、继承方式(public、protected、private)、赋值兼容转换、作用域问题、默认成员函数规则、继承与友元、静态成员、多继承及菱形继承问题,并对比了继承与组合的优缺点。最后总结指出,虽然继承提高了代码灵活性和复用率,但也带来了耦合度高的问题,建议在“has-a”和“is-a”关系同时存在时优先使用组合。
1051 6
|
存储
阿里云轻量应用服务器收费标准价格表:200Mbps带宽、CPU内存及存储配置详解
阿里云香港轻量应用服务器,200Mbps带宽,免备案,支持多IP及国际线路,月租25元起,年付享8.5折优惠,适用于网站、应用等多种场景。
3536 0
|
存储 缓存 NoSQL
内存管理基础:数据结构的存储方式
数据结构在内存中的存储方式主要包括连续存储、链式存储、索引存储和散列存储。连续存储如数组,数据元素按顺序连续存放,访问速度快但扩展性差;链式存储如链表,通过指针连接分散的节点,便于插入删除但访问效率低;索引存储通过索引表提高查找效率,常用于数据库系统;散列存储如哈希表,通过哈希函数实现快速存取,但需处理冲突。不同场景下应根据访问模式、数据规模和操作频率选择合适的存储结构,甚至结合多种方式以达到最优性能。掌握这些存储机制是构建高效程序和理解高级数据结构的基础。
1194 1
|
存储 弹性计算 固态存储
阿里云服务器配置费用整理,支持一万人CPU内存、公网带宽和存储IO性能全解析
要支撑1万人在线流量,需选择阿里云企业级ECS服务器,如通用型g系列、高主频型hf系列或通用算力型u1实例,配置如16核64G及以上,搭配高带宽与SSD/ESSD云盘,费用约数千元每月。
1679 0
|
存储 编译器 C语言
【C语言篇】数据在内存中的存储(超详细)
浮点数就采⽤下⾯的规则表⽰,即指数E的真实值加上127(或1023),再将有效数字M去掉整数部分的1。
1207 0
|
存储
共用体在内存中如何存储数据
共用体(Union)在内存中为所有成员分配同一段内存空间,大小等于最大成员所需的空间。这意味着所有成员共享同一块内存,但同一时间只能存储其中一个成员的数据,无法同时保存多个成员的值。