存储类型关键字总结

来源:互联网 发布:北京java开发培训班 编辑:程序博客网 时间:2024/05/19 02:04

最近写了个程序,由于没有深入了解c中几个存储类型关键字如何使用,导致程序功能一直无法实现,浪费了半天的时间。。。。。因此,抽空把这部分知识重新梳理一下,避免在以后开发道路上再次掉进这个坑。下面步入正题:

一、变量存储类型

      变量存储类型就是指存储变量值的存储器类型。存储类型决定:变量何时创建、何时销毁、其值保持多久。变量存在3个地方:普通内存、运行时堆栈、CPU内部的通用寄存器。

函数外声明的变量都是全局变量(作用域仅限声明该变量的c文件中,如果在其他地方调用需使用extern重新声明),编译器在编译过程中将全局变量映射在普通内存中,在程序整个执行期间该变量始终占用编译器为它分配的内存空间,而且始终保持原值,直到对该变量赋值或程序结束。

      1、auto关键字

           在函数内部声明的变量就是局部变量,作用域也就仅限于声明该变量的函数内部,函数外代码不可见。局部变量一般放在堆栈中或者CPU寄存器中。程序执行到声明该局部变量时,其被创建,程序执行离开时边自动销毁。局部变量默认就是自动变量。。。


       2、register关键字

             register关键字可以用于自动变量的声明。它提示编译器将其修饰的自动变量存储在CPU内部通用寄存器中而不是存储器中。但是,编译器并不一定遵循程序员的建议,如果有太多的自动变量被声明为存储器变量,则编译器可能只选取前面的几个存放在寄存器中,其余将保存在堆栈中;如果一个编译器拥有自己的一套寄存器优化方法,它可能会忽略register关键字,因为编译器决定哪些变量存放在寄存器中可能比程序员决定更合理。

            如果一个自动变量被编译器分配到cpu内部的寄存器存储,对这个变量使用&运算符取地址是无意义的,因为在许多机器的硬件实现中,并不为寄存器指定与外部存储器统一编址的地址。


      3、static关键字

           static关键字可能是c语言中比较多义的一个关键字,取决于使用static的不同上下文。

           static关键字一共3个不同用途:

            A、用于函数内部局部变量声明时,static关键字的作用是改变局部变量的存储类型,从自动变量改为静态变量,也就是说这个局部变量不再存储在堆栈或寄存器中,而是在编译时候由编译器分配一个静态的地址空间,但是这个变量的作用域不受影响,依然仅局限在声明它的函数内部才可以访问。一旦函数内部的局部变量被声明为static,这个函数就有可能变得不可重入;

            B、static用于函数定义时,这个函数就只能在定义该函数的c文件中使用,该c文件以外的代码将无法调用这个函数;

            C、static用于全局变量定义时,使全局变量的作用域局限于在声明该变量的c文件中,c文件之外的代码无法访问这个变量(貌似可以通过指针访问)。


       4、extern关键字

             c语言中的全局变量和函数的作用域仅限于定义或声明这个函数或变量的c文件内部,如果需要从这个c文件之外访问这些函数或者全局变量就需要使用extern关键字。一般有2种方式使用extern:

            A、在c文件中直接声明某个其他文件中定义的函数或全局变量为extern,从而告诉编译器这个函数或变量在其他c文件中定义的;

            B、在头文件中声明某个函数或变量为extern,然后在需要引用该函数或变量的c文件中包含这个头文件(最好是通过包含头文件方法解决)。


       5、const关键字

             const关键字的用法挺复杂的。用const关键字声明一个变量是“只读的”,在c中意味着这个变量的值不能改变,但是它还是一个不能改变的变量,而不是“常量”,

           int const a=20;

           int array[a];     // 声明的语法有错误,因为a是变量,在编译时候a的值不确定

在定义变量时,要对它进行初始化,否则没机会再改变它了,2种情况:

         a、在声明“只读”变量时,对这个变量赋初值,如:int const  a=20;

         b、如果const关键字用来修饰函数形参,在函数调用时候会得到实参值,在函数内部不能改变其值。


         关于指针类型的:

            const int a;   // 声明a是只读的

            int const a;   // 声明a是只读的

            const int *a;  // 声明一个指向整数的指针变量a,指针值可以改变,但是这个指针指向的整数值(*a)不可改变

            int * const a; // 声明一个指向整数的指针变量a,指针值不可以改变,但是这个指针指向的整数值(*a)可以改变

            int const  * const a;//声明一个指向整数的指针变量a,指针值和指针指向的整数值(*a)都不可以改变


         注:使用const也许能产生更紧凑的代码,有些编译器在处理const关键字修饰的变量时,会将其分配在ROM的地址空间。


     6、volatile关键字

          一个定义为volatile的变量可能会意想不到地改变,编译器就不会去假设这个变量的值了。优化器在用到这个变量时必须每次都小心的重新读取这个变量的值,而不是使用保存在寄存器里的备份。如果没有volatile关键字,则编译器可能优化读取和存储,可能暂时使用寄存器中的值,如果这个变量由别的程序更新了的话,将出现不一致的现象。

      一般说来,volatile用在如下的几个地方:
       a、中断服务程序中修改的供其它程序检测的变量需要加volatile;
       b、多任务环境下各任务间共享的标志应该加volatile;
       c、存储器映射的硬件寄存器通常也要加volatile说明,因为每次对它的读写都可能由不同意义;

        volatile关键字的介绍可以参考此博客,写的很详细 ( http://www.cnblogs.com/yc_sunniwell/archive/2010/06/24/1764231.html)。

二、总结

     C语言是嵌入式开发中使用最多的语言 ,虽然很复杂,但是也体现出其灵活的一面。——以上的总结出自《嵌入式系统 高级c语言编程》,研一上的这门课,自认为这本书编写的不错,在C语言编程中遇到的常见问题都有介绍。

3 0