C语言开发单片机为啥都是全局变量形式?

01

前言

全局变量简直就是嵌入式系统的戈兰高地。冲突最激烈的双方是:

1. 做控制的工程师;

2. 做非嵌入式的软件工程师。

02

做控制的工程师特点

他们普遍的理解就是“变量都写成全局该有多方便”。我之前面试过一个非常有名的做控制实验室里出来的PhD/Master,前前后后陆续有快十个人。面试问题是用C写PID。到后面的几位面试的时候我都觉得没有看的意义了,因为全都写的是同一个风格。大概就是这样的:

float SetSpeed;float err;float err_last;float Kp,Ki,Kd;float integral;float result;
float PID(float speed){    err=SetSpeed-speed;    integral+=err;    result=Kp*err+Ki*integral+Kd*(err-err_last);    err_last=err;    return result;}

代码的特点就是所有的变量一定定义在函数外面。问他们为什么,回答是“全局变量方便调试”。

事实上在学校里做搞自动控制的人最重要的根本就是控制的结果,而不是代码本身。代码只要能工作就行。变量名污染,低耦合之类的和他们就不在同一个世界。进了公司有些人代码质量会变好,但有的还是会延续之前的习惯。前公司代码库里面凡是看不懂的代码一律都是那一两个Control Engineer写的,写完了还会用自己的名字给函数命名的那种。

要成为一个资深的嵌入式工程师相当难,一方面要有非常扎实的理论知识,同时也要有相当的那种大型的、高频CPU、多层PCB板的设计经验。嵌入式硬件工程师要学的课程主要有模拟电路设计、数字电路设计、电磁波理论等。熟悉常用的放大电路、滤波电路、电源电路设计和分析。

03

做非嵌入式的软件工程师特点

代码的特点就是所有的静态变量都不可以定义在.h文件里,必须写在.c文件里以确保别的文件没法访问它们。

别的文件真要访问怎么办?那就给每一个变量写get/set函数啊!问题是静态变量写在.c文件里编译器是没法优化get/set的。结果就大面积的变量访问要花几倍的CPU时间去做get/set的函数调用。嵌入式项目很多情况下对硬件的压榨是很极端的,CPU利用率90%都不算什么,顶到97%都是有的。(注意下这些项目是实时性要求很高的,晚一个毫秒算不完都不行。不是跑在电脑上鼠标卡一卡也无所谓的。)然后为了封装性,在代码里面塞这么多get/set吗?

04

总结

总的来说嵌入式软件里大部分的代码都是中断驱动的,天生就有很多变量是没法使用参数传递的。全局变量的存在是因为正义站在这边。但是嵌入式软件远远没有特殊到不需要按照正常软件工程方法去管理的地步。要真有人认为“嵌入式软件只要能工作就成,代码丑一点无所谓的”纯粹是软件工程水平不行,不是因为控制水平太高。

全局变量一定是要用的,管理它们也很重要。一些基本的代码规则:

  1. 如果只是文件内调用,全局变量只能写在这个.c文件里,不要写进.h文件。

  2. 如果有文件外调用,全局变量要写在.h文件里。

  3. .h里面的全局变量全局可读,但是只有本文件组可以写。别的文件要写请调用set函数。

  4. 所有的全局变量无论在.h还是.c里面都要包成同名struct。哪怕只有一个变量也要写进struct里面。比如PID.c里面有一个pid_S,PID.h里面有个PID_S。这样其他人不仅可以立即识别出一个变量是project内global/文件内static/函数内local,同时还能轻松追溯到这个函数是属于哪个文件的。

  5. 不要写函数内的static变量。函数内的static变量在实际的项目中几乎就是bug生成器,没法简单的reset。而且对unit test非常不友好。

声明:

本文于网络整理,版权归原作者所有,如来源信息有误或侵犯权益,请联系我们删除或授权事宜。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/338995.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

ajax get请求_python测试开发django50.jquery发送Ajax请求(get)

前言有时候,我们希望点击页面上的某个按钮后,不刷新整个页面,给后台发送一个请求过去,请求到数据后填充到html上,这意味着可以在不重新加载整个网页的情况下,对网页的某部分进行更新。Ajax可以完美的实现。…

primefaces_PrimeFaces Mobile入门

primefaces介绍 如果您已经开发了利用PrimeFaces的应用程序,或者打算开发可在台式机和移动设备上使用的Web应用程序,请考虑将PrimeFaces Mobile用于您的移动实施。 这篇博客文章将介绍一些基础知识,以帮助您开始为现有的PrimeFaces应用程序开…

C语言指针这些使用技巧值得收藏!

指针用的好犹如神助,用不好会让你叫苦连连,但大多数人是用不好指针的,所以后来的很多语言都把指针封装,屏蔽。比如JAVA,java是没有指针的,但是很多地方都用到指针,不过不对用户开放,…

mysql数据库中的int类型_MySQL中int(M)和tinyint(M)数值类型中M值的意义

在一开始接触MySQL数据库时,对于int(M)及tinyint(M)两者数值类型后面的M值理解是最多能够插入数据库中的值不能大于M;后来工作后,也是一边学习一边使用,之后的理解是其中的M的意思是插入数据库中的值的字符长度不能大于M&#xff…

api怎么写_使用Node.js原生API写一个web服务器

Node.js是JavaScript基础上发展起来的语言,所以前端开发者应该天生就会一点。一般我们会用它来做CLI工具或者Web服务器,做Web服务器也有很多成熟的框架,比如Express和Koa。但是Express和Koa都是对Node.js原生API的封装,所以其实不…

C语言预处理命令分类和工作原理

C语言编程过程中,经常会用到如 #include、#define 等指令,这些标识开头的指令被称为预处理指令,预处理指令由预处理程序(预处理器)操作。相比其他编程语言,C/C 语言更依赖预处理器,故在阅读或开…

查看mysql用户权限_mysql 如何查看该数据库用户具有哪些权限?

展开全部背景在了解动态权限之前,我们先回顾下 MySQL 的权限列表。权限列表大体分为服务级别和表级别,列级别以32313133353236313431303231363533e59b9ee7ad9431333433633464及大而广的角色(也是MySQL 8.0 新增)存储程序等权限。我们看到有一个特殊的 SU…

注释嵌套注释_注释,无处不在的注释

注释嵌套注释十年前的2004年 , Java 1.5开始提供注释。 很难想象没有此功能的代码。 实际上,首先引入了注释,以减轻开发人员编写繁琐的样板代码的痛苦,并使代码更具可读性。 考虑一下J2EE 1.4(没有可用的注释&#xff…

a标签跳到另一个页面指定选项卡_HTML常用标签

本篇文章主要是对a、img和table标签用法介绍:a标签:可称为锚元素,主要功能是创建通向其他网页、文件、同一页面的其他位置、电子邮件地址或其他任何url地址的超链接;1.img标签:发出get请求并显示返回的图片1.常用属性&…

c语言也能用模板方法模式?

模式动机在嵌入式的应用场景中,管理资源(例如文件、内存)是一件非常麻烦、非常容易出错的事情。因为在分配资源后,还必须释放资源。例如fopen()打开文件后,必须要使用fclose()来关闭文件,而使用malloc申请内存资源后,就…

游戏 服务器 微服务_整体服务器与微服务

游戏 服务器 微服务介绍 刚开始时,由于要求简单,所以应用程序既简单又小。 随着时间的要求和需求的增长,我们的应用程序变得越来越大,越来越复杂。 这就导致了将单片服务器开发和部署为一个单元。 在某种程度上,微服务…

数据与ELF数据节-计算机系统基础题目

实验内容:修改二进制可重定位目标文件“phase1.o”的数据(.data)节内容(不允许修改其他节),使其与main.o模块如下链接后运行时输出目标字符串“123456789”。 实验步骤: 1. 使用objdump工具获得…

sqlserver拼接sql插入table_10个SQL技巧

介 绍为了理解这 10 个 SQL 技巧的价值,首先需要了解下 SQL 语言的上下文。为什么我要在 Java 会议上讨论 SQL 呢?(我可能是唯一一个在 Java 会议上讨论 SQL 的了)下面讲下为什么:从早期开始,编程语言设计者就有这种的愿望&#x…

【C语言笔记】指定初始化器

C99增加了一个新特性:指定初始化器(designated initializer)。利用该特性可以初始化指定的数组元素,也可以初始化指定的结构体变量。本文主要分享:使用指定初始化器初始化数组。例如,只初始化数组中的最后一个元素。对于传统的C初…

java锁性能对比_提高Java的锁性能

java锁性能对比Plumbr是唯一可以通过解释应用程序性能数据来自动检测Java性能问题根本原因的解决方案。 几个月前,我们在Plumbr中引入了锁定线程检测之后,我们开始收到类似于“嘿,太好了,现在我知道是什么导致了性能问题&#xf…

binlog日志_MySQL三大日志binlog、redo log和undo log

点击蓝色“JavaKeeper”关注我哟加个“星标”,一起成长,做牛逼闪闪的技术人Keeper导读:日志是mysql数据库的重要组成部分,记录着数据库运行期间各种状态信息。mysql日志主要包括错误日志、查询日志、慢查询日志、事务日志、二进制…

C 语言精髓之变参函数

我们以 printf 这个 very 熟悉的函数为例,来分析一下变参函数。先看下 printf 函数的定义:int printf(const char *fmt, ...){ int i; int len; /* va_list 即 char * */va_list args;va_start(args, fmt); /* 内部使用了 va_arg() */len v…

lambda捕获this_非捕获Lambda的实例

lambda捕获this大约一个月前,我在Java 8的lambda表达式框架下总结了Brian Goetz的观点 。 目前,我正在研究有关默认方法的文章,令我惊讶的是,我又回到了Java处理lambda表达式的方式。 这两个功能的交集可能会产生微妙但令人惊讶的…

mysql8 安装_MySQL8.x安装使用

1.下载网址https://dev.mysql.com/downloads/mysql/下载要登录,可以使用Oracle账户登录2.安装MySQL服务下载好的解压到D:developer目录下配置MySQL(windows下是my.ini,Linux下是my.cnf)[mysql]# 设置mysql客户端默认字符集default-character-setutf8[mys…

从原理到方法,一文讲清如何应对C语言内存泄露!

可能不少开发者都遇到过内存泄漏导致的网上问题,具体表现为单板在现网运行数月以后,因为内存耗尽而导致单板复位现象。一方面,内存泄漏问题属于比较浅显的错误,此类问题遗漏到现网,影响不好;另一方面&#…