0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

通过一些附加信息和有用的实现技术对C函数的探索

multisim 来源:multisim 作者:multisim 2020-09-27 11:11 次阅读
加入交流群
微信小助手二维码

扫码添加小助手

加入工程师交流群

在本文中,我们将通过一些附加信息和一些有用的实现技术来结束对C函数的探索。

基本的C函数(例如,一个或两个参数和一个返回值)并不复杂。但是,C函数非常灵活,通过超越基础知识,您可以更轻松地编写代码,并将一些有益的特性引入固件。

1.将函数原型放入头文件中

有时我想知道一个人是否必须是计算机科学专业才能完全理解C语言功能原型。这确实是一个相当复杂的问题。我认为固件工程师可以放心地忽略这些细节,而只需采取以下标准操作:始终为您的功能提供一个原型,并将这些原型放置在头文件中。

函数原型是一行代码,为编译器提供函数自变量和返回值的数据类型。例如:

float ArithmeticMean(char Value1,char Value2,char Value3);

复制代码

实际上,不必包含输入参数的名称,因为此时编译器希望知道的只是数据类型。因此,您也可以按如下方式编写原型:

float ArithmeticMean(char,char,char);

复制代码

我更喜欢包含参数名称,这可能是因为它允许我通过从函数定义中复制和粘贴来创建函数原型。
当函数原型被遗漏或放错位置时,可能会发生奇怪的事情,而根据我的经验,消除这些问题的最简单方法是将所有函数原型放置在项目的所有源文件中包含的头文件中。这样可以确保您可以安全地在任何源文件中使用任何函数,因为在调用每个函数之前,总是会对其进行声明(即,在头文件中)。

例如,以下代码段摘自一个名为“ Project_DefsVarsFuncs.h”的文件。

//function prototypes

void Delay_us(unsigned int DelayCount);

void Delay_10ms(unsigned int DelayCount);

void Delay_seconds(unsigned int DelayCount);

void Update_LCD(unsigned char SensorNumber, unsigned longdisplayValue);

void LCD_Clear_All();

复制代码

此头文件包含在我的源文件中,如下所示:

//-----------------------------------------------------------------------------

// Includes

//-----------------------------------------------------------------------------

#include "Project_DefsVarsFuncs.h"

复制代码

2.将函数声明为静态以避免命名冲突
随着固件项目变得越来越大和越来越复杂,您可能会发现要在不同的源文件中重用相同的功能名称。您可以使用“ static”关键字来完成此操作。如上所述,在这种情况下,您不会将函数原型放置在头文件中。
“ static”关键字将功能范围限制为一个源文件。这使您可以对不同源文件中的不同功能使用相同的功能名称。在下面显示的示例中,该项目需要三个不同的ProcessData()函数-一个用于分析ADC数据,一个用于响应UART命令,另一个用于处理I 2 C消息。

我将“ static”关键字放在函数原型的前面,然后函数原型移到源文件的顶部(即,在由函数体内的处理器指令组成的“正常”代码之前)。
当多个工程师将要从事同一固件项目时,“ static”关键字也很方便。如果两个工程师正在不同的源文件中工作,则使用静态功能可以使工程师A选择功能名称,而不必担心工程师B将为不同功能选择相同名称的可能性。

3.使用指针将数组传递给函数
嵌入式应用程序经常使用数组-传感器读数,ADC值,短ASCII消息等序列。在这种开发环境中,函数似乎有点尴尬,因为您无法将数组传递给C函数。确实,您不能像传递单个变量那样传递数组,但是可以使用指针为函数提供对数组数据的访问权限。
如果将指针作为参数之一,然后在调用函数时传递数组标识符,则函数主体中的语句可以使用该指针读取和修改数组的内容。如果您对此概念感到有些困惑,建议您先阅读有关C语言中数组的文章 ,然后阅读有关指针的第一篇文章。

4.您可以使用指针调用函数
指针是保存内存地址的变量。该地址通常标识变量或数组第零个元素的位置。但是,指针也可以指向函数。

如果您已经阅读了有关C函数的第一篇文章,您就会知道函数存储在代码存储器的特定位置,就像变量存储在数据存储器的特定位置一样。如果存储在指针中的值是函数的起始地址,则可以使用指针来调用该函数。如果更改指针的值使其等于不同函数的起始地址,则可以使用同一指针来调用该不同函数。
以下代码段显示了如何声明可与具有三个char参数和返回类型float的函数一起使用的函数指针。

float(* Ptr_to_Function)(char,char,char);

复制代码

数组标识符本质上是指向数组第零个元素的指针。同样,功能名称被解释为功能的起始地址(在代码存储器中)。因此,可以将函数分配给函数指针,如下所示:

Ptr_to_Function = ArithmeticMean;

复制代码

现在,您可以使用Ptr_to_Function调用函数ArithmeticMean()。以下两个语句是等效的:

Average = ArithmeticMean(Temperature1, Temperature2, Temperature3);

Average = (*Ptr_to_Function)(Temperature1, Temperature2, Temperature3);

复制代码

5.尽可能使用局部变量
我认为,在许多情况下,我们的本能是在源文件的顶部定义所有变量,然后将其保留在该位置。但是,养成在函数中使用局部变量的习惯是很好的。局部变量的范围仅限于定义它的功能。换句话说,变量是在调用函数时创建的,并在函数完成其任务后消失。
我推荐局部变量有两个原因。首先,它们允许您在不同的函数中重用相同的变量名。复杂的项目可能包含许多需要基本变量的功能,例如循环计数器。我喜欢对循环计数器重复使用“ n”,而不是逐步遍历字母表中的所有字母。
其次,使用局部变量可能会导致更快的代码。我不是编译器专家,但是我认为局部变量很可能放在寄存器中而不是存储位置,并且访问寄存器要比访问内存快。

寄存器是处理器的组成部分,可以快速读取和写入数据。

结论

责任编辑:xj

原文标题:在C语言固件中使用功能的五个技巧

文章出处:【微信公众号:multisim】欢迎添加关注!文章转载请注明出处。

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • C语言
    +关注

    关注

    183

    文章

    7646

    浏览量

    146108
  • 固件
    +关注

    关注

    11

    文章

    572

    浏览量

    25232

原文标题:在C语言固件中使用功能的五个技巧

文章出处:【微信号:A1411464185,微信公众号:multisim】欢迎添加关注!文章转载请注明出处。

收藏 人收藏
加入交流群
微信小助手二维码

扫码添加小助手

加入工程师交流群

    评论

    相关推荐
    热点推荐

    如何使用 powerquad 加速器中的一些功能以及 CMSIS 原始实现中的一些功能?

    )。 如何使用 powerquad 加速器中的一些功能以及 CMSIS 原始实现中的一些功能。 Example: I do not want to call arm_mat_trans_q15 powerquad
    发表于 04-03 06:37

    探索MAX20463:实现USB Type - A到Type - C的完美转换

    Type-C,接口的变化带来了更好的使用体验和更高的数据传输效率。然而,对于一些已经采用USB Type-A接口的设备来说,如何实现向Type-C接口的转换成为了
    的头像 发表于 02-08 11:50 586次阅读

    C语言中一些令人震惊的结构介绍

    C语言同意一些令人震惊的结构,下面的结构是合法的吗,如果是它做些什么? int a = 5, b = 7, c; c = a+++b; 考察点: 这个问题将作为这个测验的
    发表于 12-23 08:15

    使用setjmp及longjmp函数处理异常

    使用setjmp和longjmp函数:这是种用于实现非局部跳转的方法,就是在程序中设置个跳转点,并在某些情况下跳转到该跳转点,从而绕过中间的一些
    发表于 12-11 08:00

    复杂的软件算法硬件IP核的实现

    实现技术细节,知道这些技术细节将有利于在使用 C 语言编写算法时实现一些有针对性的优化。
    发表于 10-30 07:02

    蜂鸟E203的浮点指令集F的一些实现细节

    蜂鸟E203的浮点指令集F的一些实现细节 既然E203不是多发射,且为了节省面积,一些指令使用FPU内的同个子模块来执行,即FPU同时只能进行
    发表于 10-24 08:57

    ‌WINCS02附加技术解析与开发指南

    Microchip Technology WINCS02附加板是款高效、低成本的开发平台,用于评估和演示Microchip低功耗Wi-Fi^®^ WINCS02PC模块的特性和功能。该附加板符合
    的头像 发表于 09-30 09:45 790次阅读
    ‌WINCS02<b class='flag-5'>附加</b>板<b class='flag-5'>技术</b>解析与开发指南

    ‌RNWF02附加技术解析与开发指南

    ,而且包含个板载MCP2200 USB转UART转换器,可实现开箱即用评估。控制接口所需的信号连接到附加板的板载连接器,以实现灵活性和快速原型设计。该
    的头像 发表于 09-30 09:33 785次阅读
    ‌RNWF02<b class='flag-5'>附加</b>板<b class='flag-5'>技术</b>解析与开发指南

    请问gcc编译是怎么实现个未被调用的函数最终不被链接到固件中的?

    如题,平时在一些项目中,看到我写的一些未发生调用的函数,在固件里面找不到,初步断定是gcc编译处理了,但不知道它是怎么实现的,想了解下其原理是什么。 有了解这块的大佬,欢迎指点指点。谢
    发表于 09-28 11:40

    【原创】TDMS设置下个写入位置函数的摸索

    初始位置,循环覆盖写入,但是长时间都没成功实现。随后勉强实现此功能,但还是理解不了,把一些关键信息记录下来,以备用,有人熟悉函数的应用,感谢
    发表于 08-11 20:54

    【「DeepSeek 核心技术揭秘」阅读体验】第三章:探索 DeepSeek - V3 技术架构的奥秘

    存在资源利用率不高的问题,但它是基础探索,让 我看到将模型分段处理以实现流水线作业的初步尝试。 而 GPipe 方法的改进,通过微批次处理减少并行气泡,如同给流水线 “疏通血管”,让计算设备的闲置
    发表于 07-20 15:07

    【BPI-CanMV-K230D-Zero开发板体验】+TFT屏显示驱动及信息显示

    。 图1 输出信息 在连接显示屏的情况下,其显示效果如图2所示,说明该程序对这款显示屏还是起一些作用的。只是程序中以指定色彩显示“你好世界~”的语句并没有执行效果。 图2 测试效果 有鉴于此,只好自行
    发表于 07-02 11:03

    深入理解C语言:函数—编程中的“积木块”艺术

    在编程的世界里,函数就像建筑中的“积木块”——它们是构建复杂程序的基石。通过灵活组合这些模块,开发者能打造出功能强大且结构清晰的代码。函数之所以成为C语言的核心,正是因为它解决了编程中
    的头像 发表于 06-30 17:26 2026次阅读
    深入理解<b class='flag-5'>C</b>语言:<b class='flag-5'>函数</b>—编程中的“积木块”艺术

    Debian和Ubuntu哪个好一些

    兼容性对比Debian和Ubuntu哪个好一些,并为您揭示如何通过RAKsmart服务器释放Linux系统的最大潜能。
    的头像 发表于 05-07 10:58 1390次阅读

    如何添加一些网络上的库到mpy固件的说明或手册教程?

    下有没有关于如何添加一些网络上的库到mpy固件的说明或手册教程? 问题2: 关于mpy的image库在哪里能了解学习内部代码,只了解一些python,想知道怎么从c转换成mpy能调用的,自己写的
    发表于 04-29 08:16