这个问题总的来说重点并不在于全局变量,而是面向对象。请看完描述。 首先,主要问题在于:函数全局地持有状态,导致这些功能几乎没法操作多个实例。(重点在于持有状态,而不是全局变量。) 比如:OLED12864_Write(data, len) 那么想用一个单片机操作多个屏幕怎么办呢?OLED12864_2_Write吗,那些变量是不是全都要复制一遍改个名? (操作多块屏幕并不算钻牛角尖,12864这种级别的硬件完全有需求的可能。而且主要是举个例子,其他设备也是同样的。) 问题的重点并不在于全局变量,全局变量在嵌入式里并不是什么坏东西,提问者本人自己也经常用。反而是不可重入/单例模式才很让人不解。 尤其是在远未达到CPU/内存/系统上限的环境下,这种面向过程的方法导致一个功能完全没有拓展的能力。 实际上把这些函数写成可重入的(只操作传入的对象,而函数本身不持有状态),并不会造成什么性能开销。理由: - 确定性:对象实例本身也可以定义成全局的,从而不使用malloc/new,又保持了确定性。
- 调试和仿真:按照1的用法,这些实例完全可以使用传统的方法调试:直接用IDE查看和修改变量。
- 内存占用:不会额外产生浪费,多少个硬件就定义多少个对象实例。同时,软件架构上保持了拓展能力。
- 传参:仅多传入一个指针。这个指针如果不能由调用者用传入,就需要函数本身自己去获取全局变量,这个开销总是存在的。
- 访存:对象实例结构体的成员变量可以用“基址+偏移量”的方式来寻址,而散装的全局变量同样也要获取地址再访问内存。
除非是特殊环境,跟硬件或物理世界紧密绑定。但这种环境,应该是特定领域技术的主场;所用到的编程思维不应该是通用单片机/嵌入式编程的共识。以下是一些例子: - 环路控制需要快速响应和确定性,跟CPU核、中断、硬件、系统外设紧密绑定。
- 内存极度紧张,不过这种地方用汇编可能更好。
- 计算机系统架构特殊,需要按照特定方法编程。
- 该功能本身就是全局的,比如RTOS本身。
|