持续更新!
不要乱定义变量类型
以前写程序,当需要一个新的变量时,不管函数内还是函数外的,直接在程序开头定义,虽然不是原则上的错误,但是很不可取的作法。下面说一下,C语言中变量类型的有关概念。从变量的作用范围来分,分为局部变量和全局变量:
-
全局变量:是在函数外定义的变量,全局变量在程序全部执行过程中都占用资源,全局变量过多使程序的通用性变差,因为全局变量是模块间耦合的原因之一。
-
局部变量:在函数内部定义的变量,只在函数内部有效。
从变量的变量值存在的时间分为两种:
-
静态存储变量:程序运行期间分配固定的存储空间。
-
动态存储变量:程序运行期间根据需要动态地分配存储空间。
具体又包括四种存储方式:
-
auto
-
static
-
register
-
extern
不加说明默认为auto型,即动态存储,如果不赋初值,将是一个不确定的值。而将局部变量定义为static型的话,则它的值在函数内是不变的,且初值默认为0。编译时分配为静态存储区,可以被本文件中的各个函数引用。如果是多个文件的话,如果在一个文件中引用另外文件中的变量,在此文件中要用extern说明。不过如果一个全局变量定义为static的话,就只能在此一个文件中使用。register定义寄存器变量,请求编译器将这个变量保存在CPU的寄存器中,从而加快程序的运行。
特殊关键字const volatile的使用
const
const用于声明一个只读的变量。
const unsigned char a=1;//定义a=1,编译器不允许修改a的值
作用:保护不希望被修改的参数。
volatile
一个定义为volatile的变量是说这变量可能会被意想不到地改变,这样,编译器就不会去假设这个变量的值了。精确地说就是,优化器在用到这个变量时必须每次都小心地重新读取这个变量的值,而不是使用保存在寄存器里的备份。
static int i=0; int main(void) { ... while (1) { if (i) dosomething(); } } /* Interrupt service routine. */ void ISR_2(void) { i=1; }
程序的本意是希望ISR_2中断产生时,在main当中调用dosomething函数,但是,由于编译器判断在main函数里面没有修改过i,因此可能只执行一次对从i到某寄存器的读操作,然后每次if判断都只使用这个寄存器里面的“i副本”,导致dosomething永远也不会被调用。如果将将变量加上volatile修饰,则编译器保证对此变量的读写操作都不会被优化(肯定执行)。
一般说来,volatile用在如下的几个地方:
-
中断服务程序中修改的供其它程序检测的变量需要加volatile;
-
多任务环境下各任务间共享的标志应该加volatile;
-
存储器映射的硬件寄存器通常也要加volatile说明,因为每次对它的读写都可能由不同意义。register