C 语言中函数的高效学习方法实操在内存函数中

在 C 语言我们学习了字符串的一系列操作,比如拷贝,比较等一系列的操作,那么是否有更加全面的函数呢,现在我们来学习直接通过内存访问来操作一些数据的函数

首先我提出一些学习方法,在 C 语言库中有许许多多的函数,而很多同学觉得有些函数过两天就忘了,分享一下我在学习各种很重要的函数时一些实用性很强的学习建议

1.关注函数的类型,返回类型,参数类型,参数名,参数个数、

2.关注函数的作用,通过作用来更好的理解函数的各种参数和返回类型,例如 strstr 函数,这个函数是寻找子串,所以参数肯定至少有两,一个待查找串,一个模板串,而且是查找,所以找到了会返回一个地址,那这个函数的返回类型就是 char*

3.手动的去实现一些函数,例如上节博客的字符串函数,以及这节的内存操作函数,手动去实现,不仅仅可以增加我们对函数的认识,还可以从中获取一些,操作的算法,甚至能学习到指针的实现过程,这是极大的学习函数和算法,逻辑的宝贵途径

1.Memcpy

内存拷贝函数,这个函数是处理内存不重叠时所使用的,如有内存重叠,在同一块内存上,我们应该使用 memmove 函数,下面我给出这个函数的类型

void * memcpy(void *dest,void *src,size_t num)

返回类型是泛型指针void*,也代表了这个函数可以进行各种数据的操作,返回拷贝内容的起始地址dest,后面的参数 size_t  num 指的是拷贝的字节大小,整体的功能是将 src里的内容拷贝到 dest 里并返回 dest 的地址

下面,我给出这个函数的模拟实现

void * my_memcpy(void * dest,void * src,size_t num)
{
    void * ret = dest;//保留起始位置,方便返回
    assert(dest && src);
    while(num--)//循环num 次,按字节交换
    {
        *(char *)dest = *(char *)src;
        dest = (char *)dest +1;
        src = (char*)src + 1;    
    }
    return ret;
}

2.Memmove

这个函数与上一个函数的功能更加强大,可以处理带有内存重叠的拷贝

void * memmove(void *dest,void *src,size_t num)

比如,当有一个数组,需要在数组内部实现拷贝且带有内存的重叠时,就可以使用这个函数

给出这个函数的模拟实现

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

2.实现原理

注意,这个函数内部的实现思想是重要的,在后续实现顺序表时,就会用到这种,怎样拷贝才不会让值覆盖,所以,对这个函数的内部实现清楚,是让自己能力提升的重要因素

我来讲解一下这个函数

在 memcpy 中,我们没有关心 dest 与 src 的位置前后问题,试想,如果 dest 在 src 后面,我们在从src 的开始地址复制时,值就会被覆盖,比如 dest 在[4],src在[2],我们要向后拷贝两个单位,

比如从 下标为 2 开始往后复制三个单位到下标为 3 的数据,2->3,3->4,注意,当 3 拷贝到 4 时,3 已经被 2 的值覆盖了,所以 4 也是 2 的值,此时就发现了问题,我们的模拟实现是有问题的,所以我们要分情况,在这种情况下,我们应该从后往前开始拷贝,在代码中就体现在以下地方

按 dest 和 src 的位置前后分类,当 dest 在 src 前面时,我们应该从前往后复制,当 dest 在 src 后面时,我们应该从后往前复制,我对此总结为:

前前后后,即当dest 在 src 前面时,从前往后复制,当 dest 在 src 后面时,从后往前复制

3.Memset

这个函数的功能类似于初始化一组数据,但在运用时有局限,以下是函数定义

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

有三个参数,第一个指针指向待开始的设置的数据,第二个参数是改变后的元素,第三个是设置多少个字节。下面给出模拟实现

void *my_memset(void *s, int c, size_t n) {
    if (s == NULL) return s;
    
    unsigned char *p = (unsigned char *)s;
    unsigned char uc = (unsigned char)c;
    
    // 指针遍历
    while (n--) {
        *p++ = uc;
    }
    
    return s;
}

但注意,此函数在使用时是有局限的,例如在此时

当设置的元素是整形时,一个整形是四个字节,而 memset 是按字节去填充内容,那么在一个整形内就会填充四次,填充完之后,那这个整形早已不是我们所期望的目标整形,当然也并不是所有整形都不行,当设置元素为 0 时,就可以解决这个问题。

好了,到现在我们重要的内存操作讲解就已经完毕了,在我讲解时,都采取了我一开始总结的学习函数的方法,关注函数的返回类型和各个参数,关注函数的作用,关注函数的模拟实现,相信你如果以后按照这种思想学习函数时,会对函数的使用了如指掌。

                                                                                          以上纯个人观点,如有不足,大家补充

根据原作 https://pan.quark.cn/s/459657bcfd45 的源码改编 Classic-ML-Methods-Algo 引言 建立这个项目,是为了梳理和总结传统机器学习(Machine Learning)方法(methods)或者算法(algo),和各位同仁相互学习交流. 现在的深度学习本质上来自于传统的神经网络模型,很大程度上是传统机器学习的延续,同时也在不少时候需要结合传统方法现. 任何机器学习方法基本的流程结构都是通用的;使用的评价方法也基本通用;使用的一些数学知识也是通用的. 本文在梳理传统机器学习方法算法的同时也会顺便补充这些流程,数学上的知识以供参考. 机器学习 机器学习是人工智能(Artificial Intelligence)的一个分支,也是现人工智能最重要的手段.区别于传统的基于规则(rule-based)的算法,机器学习可以从数据中获取知识,从而现规定的任务[Ian Goodfellow and Yoshua Bengio and Aaron Courville的Deep Learning].这些知识可以分为四种: 总结(summarization) 预测(prediction) 估计(estimation) 假想验证(hypothesis testing) 机器学习主要关心的是预测[Varian在Big Data : New Tricks for Econometrics],预测的可以是连续性的输出变量,分类,聚类或者物品之间的有趣关联. 机器学习分类 根据数据配置(setting,是否有标签,可以是连续的也可以是离散的)和任务目标,我们可以将机器学习方法分为四种: 无监督(unsupervised) 训练数据没有给定...
评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值