当前位置: 首页 > news >正文

精通C语言(1.内存函数)

  • 🌈🌈🌈这里是say-fall分享,感兴趣欢迎三连与评论区留言
  • 🔥🔥🔥专栏:《C语言入门知识点》、《C语言底层》
  • 💪💪💪格言:今天多敲一行代码,明天少吃一份苦头

前言:

随着指针篇的完结,C语言大部分知识点其实已经全部被学完,下面我们来看一下几个C语言内置的一些内存函数,包括memcpy、memmove、memset和memcmp,如果各位观众有兴趣的话,不妨跟着我来了解一下他们的用法,快记好笔记~


文章目录

    • 前言:
    • 正文:
      • 1. memcpy的使用和模拟实现
        • 1.1 memcpy的使用
        • 1.2 memcpy的模拟实现
      • 2. memmove的使用和模拟实现
      • 3. memset的使用
      • 4. memcmp的使用


正文:

1. memcpy的使用和模拟实现

1.1 memcpy的使用

首先我们来了解一下memcpy的标准形式与参数
它的作用是将一些值拷贝在另一处

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

void*为返回类型

void* destination为“复制目标地点”

const void* source为“复制源”

size_t num为“复制值的字节数”

接着我们来看一下memcpy究竟是什么效果

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

运行结果:

0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
1 2 3 4 5 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
1.2 memcpy的模拟实现

首先参数的确定是和原函数一样的,这样的话确定了参数,然后我们来思考一下怎么去”copy
还记得我们之前qsort函数是怎么交换的吗?
以下展示:

在这里插入图片描述

同理,我们这里也用这个方法,因为不管是什么类型,都能以单个字节来赋值或者说拷贝:

*(char*)dest = *(char*)src;dest = (char*)dest + 1;src = (char*)src + 1;

解决了这个大问题以后,我们只需要确定返回的是“目标地址”就好了,下面是完整代码和使用:

#include <stdio.h>
#include <string.h>
#include <assert.h>void* my_memcpy(void* dest, const void* src, size_t num);int main()
{int arr1[10] = { 0,1,2,3,4,5,6,7,8,9 };int arr2[20] = { 0 };int i = 0;for (i = 0; i < sizeof(arr2) / sizeof(arr2[0]); i++){printf("%d ", arr2[i]);}printf("\n");my_memcpy(arr2, arr1 + 1, 20);for (i = 0; i < sizeof(arr2) / sizeof(arr2[0]); i++){printf("%d ", arr2[i]);}return 0;
}void* my_memcpy(void* dest, const void* src, size_t num)
{const void* ret = dest;assert(dest && src);while (num--){*(char*)dest = *(char*)src;dest = (char*)dest + 1;src = (char*)src + 1;}return ret;
}

运行结果完全一致:

0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
1 2 3 4 5 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0

2. memmove的使用和模拟实现

memmove是干什么的,和memcpy有什么区别?
在讨论这个问题之前,我们先再用memcpy来拷贝一下:

#include <stdio.h>
#include <string.h>
#include <assert.h>void* my_memcpy(void* dest, const void* src, size_t num);int main()
{int arr1[10] = {0,1,2,3,4,5,6,7,8,9};int arr2[20] = { 0 };int i = 0;for (i = 0; i < sizeof(arr1) / sizeof(arr1[0]); i++){printf("%d ", arr1[i]);}printf("\n");my_memcpy(arr1 + 3, arr1, 20);for (i = 0; i < sizeof(arr1) / sizeof(arr1[0]); i++){printf("%d ", arr1[i]);}return 0;
}void* my_memcpy(void* dest, const void* src, size_t num)
{const void* ret = dest;assert(dest && src);while (num--){*(char*)dest = *(char*)src;dest = (char*)dest + 1;src = (char*)src + 1;}return ret;
}

运行结果:

0 1 2 3 4 5 6 7 8 9
0 1 2 0 1 2 0 1 8 9

我们发现他并没有完全的拷贝到位,而是出现了重复,如果仔细分析的话就会发现是因为之前拷贝的影响到了后面的值(因为有交集)
这样的话我们不妨从后面开始赋值:

while (num--)
{*((char*)dest + num)= *((char*)src + num);
}

这样的话好像出现了另一种情况,便出现了分类:
这样处理一下:

void* my_memmove(void* dest, const void* src, size_t num)
{const void* ret = dest;assert(dest && src);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;
}

如果注意细节的话就能发现这个函数其实就是my_memmove函数
接下来讲解一下什么是memmove,这个函数其实可以理解为一个memcpy的 “升级版
因为他完全可以杜绝掉拷贝有交集重叠的问题
所以,他们两个几乎完全一致:

void * memmove ( void * destination, const void * source, size_t num );

void*为返回类型

void* destination为“复制目标地点”

const void* source为“复制源”

size_t num为“复制值的字节数”

3. memset的使用

memset有点像是直接给内存赋值的一个函数

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

这里直接展示一个实例:

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

运行结果:

helloxxxxxx

通过实例我们可以发现这个函数就是把ptr这个地址以后的值赋成value,一共赋num个字节

4. memcmp的使用

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

ptr1ptr2两个是要比较的地址,num是比较的字节数

在这里插入图片描述

如果前者大就返回正值,反之为负,相等为正
这里直接拿来主义一个例子:

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

运行结果:

'DWgaOtP12df0' is greater than 'DWGAOTP12DF0'.

证明了buffer1[]更大一些,原因是g的ASCII码比G的大32

  • 本节完…
http://www.dtcms.com/a/430880.html

相关文章:

  • Radio Garden官网入口 - 全球广播电台在线收听网站|网页版|打不开
  • 基于以太坊的Dao治理系统
  • 【LeetCode_203】移除链表元素
  • LeetCode刷题记录----75.颜色分类
  • QQ可以在网站做临时会话么温州的网站建设公司
  • Java-Spring 入门指南(十七)SpringMVC--Apipostl与RestFul实战测试
  • Codeforces Round 993A Easy Problem
  • OSI模型、网络地址、与协议
  • Codeforces Round 993B. Normal Problem
  • 《嵌入式 – GD32开发实战指南(RISC-V版本)》第3章 GPIO流水灯的前世今生
  • 深圳手机网站建设哪家好表白链接生成器
  • GameObject 常见类型详解 -- 光环生成对象(AURA GENERATOR)
  • 29.CSS 3D 加载转轮 | CSS 动画效果
  • 潍坊制作网站用淘宝做公司网站
  • AMQP协议深度解析:消息队列背后的通信魔法
  • CSP-J/S复赛真实考试场景还原与备考策略
  • 攻防世界-Web-inget
  • flex布局学习记录
  • unordered_map和unordered_set的使用以及哈希表的实现
  • Powershell 管理 后台/计划 作业(六)
  • 北京网站建设公司东为企业网络营销方案策划书
  • 四川网站营销seo什么价格网站建设哪家g
  • k8s-pod的镜像升级与回滚
  • Django 从入门到进阶:构建完整的博客系统
  • XYplorer(多标签文件管理器) 多语便携版
  • 哈尔滨公告最新消息枣庄seo推广
  • 从输入网址到网页呈现:深入理解 HTTP 及其背后的网络世界
  • 建设一个网站需要什么软件抖音小程序在哪里找
  • Rust语言简介
  • 【无标题】Heartbeat高可用配置实践