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;
}

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

目录
相关文章
|
2月前
|
安全 C语言 C++
比较C++的内存分配与管理方式new/delete与C语言中的malloc/realloc/calloc/free。
在实用性方面,C++的内存管理方式提供了面向对象的特性,它是处理构造和析构、需要类型安全和异常处理的首选方案。而C语言的内存管理函数适用于简单的内存分配,例如分配原始内存块或复杂性较低的数据结构,没有构造和析构的要求。当从C迁移到C++,或在C++中使用C代码时,了解两种内存管理方式的差异非常重要。
127 26
|
7月前
|
存储 程序员 编译器
玩转C++内存管理:从新手到高手的必备指南
C++中的内存管理是编写高效、可靠程序的关键所在。C++不仅继承了C语言的内存管理方式,还增加了面向对象的内存分配机制,使得内存管理既有灵活性,也更加复杂。学习内存管理不仅有助于提升程序效率,还有助于理解计算机的工作原理和资源分配策略。
|
3月前
|
C语言 C++
c与c++的内存管理
再比如还有这样的分组: 这种分组是最正确的给出内存四个分区名字:栈区、堆区、全局区(俗话也叫静态变量区)、代码区(也叫代码段)(代码段又分很多种,比如常量区)当然也会看到别的定义如:两者都正确,记那个都选,我选择的是第一个。再比如还有这样的分组: 这种分组是最正确的答案分别是 C C C A A A A A D A B。
60 1
|
3月前
|
人工智能 机器人 编译器
c++模板初阶----函数模板与类模板
class 类模板名private://类内成员声明class Apublic:A(T val):a(val){}private:T a;return 0;运行结果:注意:类模板中的成员函数若是放在类外定义时,需要加模板参数列表。return 0;
92 0
|
9月前
|
存储 缓存 编译器
【硬核】C++11并发:内存模型和原子类型
本文从C++11并发编程中的关键概念——内存模型与原子类型入手,结合详尽的代码示例,抽丝剥茧地介绍了如何实现无锁化并发的性能优化。
401 68
|
6月前
|
存储 Linux C语言
C++/C的内存管理
本文主要讲解C++/C中的程序区域划分与内存管理方式。首先介绍程序区域,包括栈(存储局部变量等,向下增长)、堆(动态内存分配,向上分配)、数据段(存储静态和全局变量)及代码段(存放可执行代码)。接着探讨C++内存管理,new/delete操作符相比C语言的malloc/free更强大,支持对象构造与析构。还深入解析了new/delete的实现原理、定位new表达式以及二者与malloc/free的区别。最后附上一句鸡汤激励大家行动缓解焦虑。
|
6月前
|
安全 C++
【c++】继承(继承的定义格式、赋值兼容转换、多继承、派生类默认成员函数规则、继承与友元、继承与静态成员)
本文深入探讨了C++中的继承机制,作为面向对象编程(OOP)的核心特性之一。继承通过允许派生类扩展基类的属性和方法,极大促进了代码复用,增强了代码的可维护性和可扩展性。文章详细介绍了继承的基本概念、定义格式、继承方式(public、protected、private)、赋值兼容转换、作用域问题、默认成员函数规则、继承与友元、静态成员、多继承及菱形继承问题,并对比了继承与组合的优缺点。最后总结指出,虽然继承提高了代码灵活性和复用率,但也带来了耦合度高的问题,建议在“has-a”和“is-a”关系同时存在时优先使用组合。
350 6
|
7月前
|
安全 C语言 C++
彻底摘明白 C++ 的动态内存分配原理
大家好,我是V哥。C++的动态内存分配允许程序在运行时请求和释放内存,主要通过`new`/`delete`(用于对象)及`malloc`/`calloc`/`realloc`/`free`(继承自C语言)实现。`new`分配并初始化对象内存,`delete`释放并调用析构函数;而`malloc`等函数仅处理裸内存,不涉及构造与析构。掌握这些可有效管理内存,避免泄漏和悬空指针问题。智能指针如`std::unique_ptr`和`std::shared_ptr`能自动管理内存,确保异常安全。关注威哥爱编程,了解更多全栈开发技巧。 先赞再看后评论,腰缠万贯财进门。
340 0
|
8月前
|
存储 程序员 编译器
什么是内存泄漏?C++中如何检测和解决?
大家好,我是V哥。内存泄露是编程中的常见问题,可能导致程序崩溃。特别是在金三银四跳槽季,面试官常问此问题。本文将探讨内存泄露的定义、危害、检测方法及解决策略,帮助你掌握这一关键知识点。通过学习如何正确管理内存、使用智能指针和RAII原则,避免内存泄露,提升代码健壮性。同时,了解常见的内存泄露场景,如忘记释放内存、异常处理不当等,确保在面试中不被秒杀。最后,预祝大家新的一年工作顺利,涨薪多多!关注威哥爱编程,一起成为更好的程序员。
328 0
|
10月前
|
存储 缓存 C语言
【c++】动态内存管理
本文介绍了C++中动态内存管理的新方式——`new`和`delete`操作符,详细探讨了它们的使用方法及与C语言中`malloc`/`free`的区别。文章首先回顾了C语言中的动态内存管理,接着通过代码实例展示了`new`和`delete`的基本用法,包括对内置类型和自定义类型的动态内存分配与释放。此外,文章还深入解析了`operator new`和`operator delete`的底层实现,以及定位new表达式的应用,最后总结了`malloc`/`free`与`new`/`delete`的主要差异。
180 3

热门文章

最新文章