变量的作用域

所谓的作用域就是指变量起作用的范围,也就是变量的有效范围。
变量按作用域可以分为局部变量和全局变量。

局部变量

在一个函数内部声明的变量是内部变量,它只在本函数内有效,在本函数以外是不能使用的,这样的变量就是局部变量。
此外,函数的形参也是局部变量。

全局变量

在函数外声明的变量就是全局变量。
一个源文件可以包含一个后者多个函数,全局变量的作用范围是从它开始声明的位置一直到程序结束。

局部变量只有在声明它的函数范围内可以使用,而全局变量可以被作用域内所有的函数直接使用。所以在一个函数内既可以使用本函数内声明的局部变量,也可以使用全局变量。

从编程规范上讲,一个程序文件内所有的全局变量都应该定义在文件的开头部分,在文件中所有函数之前。

由于C语言函数只有一个返回值,但经常会希望一个函数可以提供多个结果值,这时就可以利用全局变量来实现。但是考虑到全局变量的一些特征,应该限制全局变量的使用,过多使用全局变量也会带来一些问题。

  • 全局变量可以被作用域内所有的函数直接引用,可以增加函数间数据联系的途径,但同时加强了函数模块之间的数据联系,使这些函数的独立性降低,对其中任何一个函数的修改都可能会影响到其他函数的执行结果,函数之间过于紧密的联系不利于程序的维护。
  • 全局变量的应用会降低函数的通用性。函数在执行的时候过多依赖于全局变量,不利于函数的重复利用。
  • 过多使用全局变量会降低程序的清晰度,使程序的可读性下降。在各个函数执行的时候都可能改变全局变量的值,往往难以清楚的判断出每个时刻各个全局变量的值。
  • 定义全局变量会永久占用单片机的内存单元,而局部变量只有进入定义局部变量的函数时才会占用内存单元,函数退出后会自动释放所占用的内存。所以大量的全局变量会额外增加内存消耗。

在编程规范上有一条原则,就是减少全局变量的使用,能用局部变量代替的就不用全局变量。

还有一种特殊的情况:C语言是允许局部变量和全局变量同名的,它们定义后在内存中占有不同的内存单元。如果在同一源文件中,全局变量和局部变量同名的,在局部变量作用域范围内,只有局部变量有效,全局变量不起作用,也就是说局部变量具有更高优先级。

从编程规范上讲,避免全局变量和局部变量重名,从而避免不必要的误解和误操作。

变量的存储类别

变量的存储类别分为自动、静态、寄存器和外部这四种。

函数中的局部变量,如果不加static这个关键字来修饰,都属于自动变量,也叫做动态存储变量。这种存储类别的变量,在调用该函数的时候系统会给他们分配存储空间,在函数调用结束后自动释放这些存储空间。动态存储变量的关键字是auto,但是这个关键字是可以省略的。

与动态变量对应的就是静态变量。首先,全局变量均是静态变量,此外,还有一种特殊的局部变量也是静态变量。即在定义局部变量时前边加上static这个关键字,加上这个关键字的变量就称之为静态局部变量,它的特点是,在整个生存期中只赋值一次,在第一次执行该函数时,它的值就是给定的那个初值,而之后在该函数所有的执行次数中,它的值都是上一次函数执行结束后的值,即它可以保持前次的执行结果。

有这样一种情况,某个变量只在一个函数中使用,但是却想在函数中多次调用期间保持住这个变量的值而不丢失,也就是说在该函数的本次调用中该变量值的改变要依赖上一次调用函数时的值,而不能每次都从初值开始。如果使用局部动态变量的话,每次进入函数后上一次的值就丢失了,它每次从初值开始,如果定义成全局变量的话,又违背了上面提到的尽量减少全局变量的使用这条原则,那么此时,局部静态变量就是最好的解决方案了。

点阵的初步认识

点阵LED显示屏作为一种现代电子媒体,具有灵活的显示面积(可以随意分割和拼装)、高亮度、长寿命、数字化、实时性等特点,应用非常广泛。

一个数码管是8个LED组成,同理,一个8 * 8的点阵就是由64个LED小灯组成。

变量进阶与点阵LED_局部变量


上图是一个点阵LED最小单元,即一个8 * 8的点阵LED,下图是它的内部结构原理图

变量进阶与点阵LED_二维数组_02

点阵的图形显示

取模软件的使用点阵显示心形

点阵的动画显示

点阵的动画显示,说到底就是对多张图片分别进行取模,使用程序算法巧妙的切换图片,多张图片组合起来就形成了一段动画,动画片、游戏等的基本原理都是如此。

点阵的纵向移动

点阵纵向上移

点阵的横向移动

二维数组

二维数组的声明方式:

数据类型 数组名[数组长度1][数组长度2];

与一维数组类似,数据类型是全体元素的数据类型,数组名是标识符,数组长度1和数组长度2分别代表数组具有的行数和列数。

数组元素的下标一律从0开始。

二维数组的元素总个数是两个长度的乘积。

二维数组在内存中存储的时候,采用行优先的方式来存储,即在内存中先存放第0行的元素,再存放第一行的元素...同一行中再按照列顺序存放。

下表为a[2][3]的存放形式

变量进阶与点阵LED_全局变量_03


二维数组的初始化分为两种情况:

unsigned char a[2][3] = { { 1, 2, 3 }, { 4, 5, 6 } };

等价于

unsigned char a[2][3] = { 1, 2, 3, 4, 5, 6 };

unsigned char a[2][3] = { { 1, 2 }, { 3, 4 } }; 等价于
unsigned char a[2][3] = { 1, 2, 0 , 3, 4, 0 };

unsigned char a[2][3] = { 1, 2, 3, 4 }; 等价于
unsigned char a[2][3] = { { 1, 2, 3 }, { 4, 0, 0 } };

二维数组初始化的时候,行数可以省略,编译系统会自动根据列数计算出行数,但是列数不能省略。

横向移动

点阵的横向移动

作者:EricsT