关键字的作用 static,extern,const,volatile,register,inline

 

关键字的作用 static,extern,const,volatile,register,inline

标签: 编译器语言存储扩展gccc
  261人阅读  评论(0)  收藏  举报
  分类:
 
c & data_structure(2) 

关键字的作用 static,extern,const,volatile,register,inline

1.static关键字的作用

(1)当用static声明函数内的局部变量时,表示这个局部变量是在静态存储区分配的空间,在函数调用结束后其占用的存储单元并不释放,仍然保留原值。此外,静态局部变量是在编译时赋一次初值,程序运行时每次调用函数都不再重新赋初值,而是使用前次函数调用结束时的值。若程序不赋初值,则编译时自动赋值0(普通局部变量不赋初值的话,其值不确定)。

(2)当用static声明在函数体外的全局变量时,表示这个全局变量只能用于本文件,而不能被别的文件引用(即使使用了extern来扩展使用域),这样就能在不同文件中使用相同的全局变量名,提高了程序的通用性和可移植性。//ps:全局变量和静态全局变量都存放在静态存储区中,都是在编译时分配内存,只是作用域不同(全局变量可以在其他文件中用extern扩展使用域)。

(3)当用static声明函数时,表示此函数只能被本文件中的其他函数调用(称为内部函数),这样在不同文件中就可以使用相同函数名,只要用static声明即可。

2.extern关键字的作用

(1)用extern声明全局变量。

a.在一个文件内声明全局变量,可以将全局变量的使用域扩展到从“声明”到文件结尾,而不是从“定义”到文件结尾。

b.在一个文件中用extern声明另一个文件定义的全局变量,可将此全局变量的作用域扩展到这个文件。

ps: 系统处理extern的过程:编译时遇到extern,先在本文件中找是否有此全局变量的定义(即a情况),若没有,则在连接时从其他文件中找此全局变量的定义(b情况)。如果找不到,则出错。

(2)当用extern在定义函数时,表示此函数可以被其他文件的函数调用。//此种情况extern可以省略,函数的定义本身就是外部可引用的的

(3)当需要使用别的文件的函数时,用extern声明所用的函数是外部函数。

(4)在C++语言中调用C编译器编译的C语言函数,要用extern "C"声明,原因是:C++语言支持函数重载,C语言不支持函数重载。函数被C++编译后在库中的名字与C语言的不同。假设某个函数的原型为:void foo(int x, int y); 该函数被C编译器编译后在库中的名字为_foo,而C++编译器则会产生像_foo_int_int之类的名字。C++提供了C连接交换指定符号extern“C”来解决名字匹配问题

声明与定义:

1.从广义上说,声明包含定义。“int a;”--既是声明也是定义。“extern A;”只是声明不是定义。

2.从狭义上说,建立了存储空间的是定义,不需要建立存储空间的是声明。

3.关键字const的作用

笼统的说,const的意思是“只能读不能写”。

(1)给读你代码的人传达非常有用的信息。例如,在函数的形参前添加const关键字意味着这个参数在函数体内不会被修改,属于"输入参数"。在有多个形参的时候,函数的调用者可以凭借参数前是否有const关键字,清晰的辨别哪些是输入参数,哪些是可能的输出参数。

 (2)合理地使用关键字const可以使编译器很自然地保护那些不希望被改变的参数,防止其被无意的代码修改,这样可以减少bug的出现。

  ps:在编译阶段需要的常数仍然只能以#define宏定义!在C语言中如下程序是非法的:

const int SIZE = 10;

char a[SIZE];//编译时SIZE仍是变量,变长数组是不允许的

几个const相关的定义实例:

(1)const int a; = int const a;

const int *p; = int const *p;

const与int前后顺序可以调换,前提是他们是紧挨在一起。

(2)const int * p与int * const p

a.const int * p----const修饰的是*p,即*p不能修改,但p可以修改。

int i=3;

int j=5;

const int * p=&i;

p=&j; //p可以在任意时候重新赋值一个新内存地址

j=80; //只要不是用*p来修改,j是可以重新赋值的

b.int * const p----const修饰的是p,即p指针所指的地址不能改,而地址空间中的值可以修改

int i=3;

int j=5;

int * const p=&i;//p被const修饰,不能重新赋值了,即不能再写p=&j。

i=8; //地址空间中的值是可以改变的

(3)int * p指针指向const int i常量的情况

const int i=5;

int *p;

p=&i; //这样是不行的,编译出错。constint 类型的i的地址是不能赋值给指向int类型地址的指针pi的。否则pi岂不是能修改i1的值了吗!

解决办法是只要将他们的类型统一就可以了,如:

const int *p;//将p定义为const int的指针

或者强制类型转换:pi=(int* ) &i;//至于是否可以通过*p来修改i的值,根据编译器不同而不同

(4)用const int * const p声明的指针

int i;

const int * const p=&i;//p的值不能修改,也不能通过*p修改i的值。但可直接修改i的值

注意: const修饰的变量,只能在定义的时候赋初值,不能在新行赋值。

const int a;

a=10;//错误,不能新行赋值。只能写成const int a=10;

4.关键字volatile的作用

一个定义为volatile的变量是说这个变量可能会被意想不到的改变,也就是说编译器不会去假设这个变量的值。当编译时用到这个变量的时候,优化器必须每次都重新读取这个变量,而不能使用寄存器里的备份。

volatile变量运用的几个例子:

(1)并行设备的硬件寄存器,如状态寄存器。每个设备在任何时刻都有可能会因为状态的变化而修改寄存器。

(2)一个中断服务子程序中访问到的非自动变量。

(3)多线程任务中被几个任务共享的变量。每个线程都有可能去修改这个变量。

5.关键字register的作用

用register定义的变量存在寄存器中,而不存在内存中。

(1)只有局部自动变量和形式参数可以作为寄存器变量。(不能让全局变量占着寄存器不放;register不和static连用)

(2)不能定义任意多个寄存器变量,处理器中寄存器变量是有限的。

6.关键字typedef的作用

声明新的类型来代替已有的类型。

使用方法:1、先按普通定义的方法写出定义体(如:int n[10];);

2、将变量名换成自己指定的类型名(int NUM[10]);

3、在前面加上typedef得到:typedef int NUM[10];

4、可以用心得类型名来定义变量了:NUM n = int n[10]

(1)typedef是在编译的时候处理的,而#define是在预编译的时候处理;

(2)typedef的使用很好的方便了程序的移植;

7,关键字inline的作用

   gcc的inline函数相对于普通extern函数来说只是在同一个文件内调用时建议编译器进行内联展开;

gcc一定会为inline函数生成一份独立的汇编码,以便其在本文件之外被调用。在别的文件内看来,这个inline函数和普通的extern函数无异;

gcc的inline函数是全局性的:在文件内可以作为一个内联函数被内联展开,而在文件外可以调用它。

你可能感兴趣的:(关键字的作用 static,extern,const,volatile,register,inline)