static inline volatile的作用

1、static

(1)先来介绍它的第一条也是最重要的一条:隐藏。

当我们同时编译多个文件时,所有未加static前缀的全局变量和函数都具有全局可见性。为理解这句话,我举例来说明。我们要同时编译两个源文件,一个是a.c,另一个是main.c。

下面是a.c的内容

[cpp] view plain

下面是main.c的内容

[cpp] view plain

程序的运行结果是:

A Hello

你可能会问:为什么在a.c中定义的全局变量a和函数msg能在main.c中使用?前面说过,所有未加static前缀的全局变量和函数都具有全局可见性,其它的源文件也能访问。此例中,a是全局变量,msg是函数,并且都没有加static前缀,因此对于另外的源文件main.c是可见的。

如果加了static,就会对其它源文件隐藏。例如在a和msg的定义前加上static,main.c就看不到它们了。利用这一特性可以在不同的文件中定义同名函数和同名变量,而不必担心命名冲突。Static可以用作函数和变量的前缀,对于函数来讲,static的作用仅限于隐藏,而对于变量,static还有下面两个作用。

(2)static的第二个作用是保持变量内容的持久。存储在静态数据区的变量会在程序刚开始运行时就完成初始化,也是唯一的一次初始化。共有两种变量存储在静态存储区:全局变量和static变量,只不过和全局变量比起来,static可以控制变量的可见范围,说到底static还是用来隐藏的。虽然这种用法不常见,但我还是举一个例子。

[cpp] view plain

程序的运行结果是:

global local static

1 10

2 9

3 8

4 7

5 6

6 5

7 4

8 3

9 2

10 1

(3)static的第三个作用是默认初始化为0。其实全局变量也具备这一属性,因为全局变量也存储在静态数据区。在静态数据区,内存中所有的字节默认值都是0x00,某些时候这一特点可以减少程序员的工作量。比如初始化一个稀疏矩阵,我们可以一个一个地把所有元素都置0,然后把不是0的几个元素赋值。如果定义成静态的,就省去了一开始置0的操作。再比如要把一个字符数组当字符串来用,但又觉得每次在字符数组末尾加’/0’太麻烦。如果把字符串定义成静态的,就省去了这个麻烦,因为那里本来就是’/0’。

2 inline

我们看下面的函数,函数体中只有一行语句:double Average(double total, int number){return total/number;}定义这么简单的函数有必要吗?实际上,它还是有一些优点的:第一,它使程序更可读;第二,它使这段代码可以重复使用。但是,它也有缺点:当它被频繁地调用的时候,由于调用函数的开销,会对应用程序的性能(时间+空间效率,这儿特指时间)有损失。例如,Average在一个循环语句中重复调用几千次,会降低程序的执行效率。那么,有办法避免函数调用的开销吗?对于上面的函数,我么可以把它定义为内联函数的形式:inline double Average(double total, int number){return total/number;}函数的引入可以减少程序的目标代码,实现程序代码的共享。  函数调用需要时间和空间开销,调用函数实际上将程序执行流程转移到被调函数中,被调函数的代码执行完后,再返回到调用的地方。这种调用操作要求调用前保护好现场并记忆执行的地址,返回后恢复现场,并按原来保存的地址继续执行。对于较长的函数这种开销可以忽略不计,,但对于一些函数体代码很短,又被频繁调用的函数,就不能忽视这种开销。引入内联函数正是为了解决这个问题,提高程序的运行效率。在程序编译时,编译器将程序中出现的内联函数的调用表达式用内联函数的函数体来进行替换。由于在编译时将内联函数体中的代码替代到程序中,因此会增加目标程序代码量,进而增加空间开销,而在时间开销上不象函数调用时那么大,可见它是以目标代码的增加为代价来换取时间的节省。◆总结:inline函数是提高运行时间效率,但却增加了空间开销。 即inline函数目的是:为了提高函数的执行效率(速度)。非内联函数调用有栈内存创建和释放的开销在C中可以用宏代码提高执行效率,宏代码不是函数但使用起来像函数,编译器用复制宏代码的方式取代函数调用,省去了参数压栈、生成汇编语言的CALL调用、返回参数、执行return等过程,从而提高速度。◆使用宏的缺点:(1)容易出错(预处理器在复制宏代码时常常产生意想不到的边际效应)例如:#define MAX(a,b)(a) > (b) ? (a) : (b)语句result = MAX(i,j) + 2 却被扩展为result = (i)>(j)?(i):(j)+2;但意却为result = ((i)>(j)?(i):(j)) + 2;(2)不可调试(3)无法操作类的私有数据成员C++函数内联机制既具备宏代码的效率,又增加了安全性,且可自由操作类的数据成员。关键字inline必须与函数定义体放在一起才能使函数真正内联,仅把inline放在函数声明的前面不起任何作用。因为inlin是一种用于实现的关键字,不是一种用于声明的关键字。许多书籍把内联函数的声明、定义体前都加了inline关键字,但声明前不应该加(加不加不会影响函数功能),因为声明与定义不可混为一谈。★声明、定义和语句声明:就是在向系统介绍名字(一个名字是一块内存块的别名),只是告诉编译器这个名字值的类型及宣告该名字的存在性,仅此而已。定义:则是分配存储空间,即具有了存储类型。语句:程序的基本组成部分,分可执行语句(定义是)和不可执行语句(声明是)。在正式编写程序语句前定义的一些全局变量或局部变量,在C中为声明,C++中为定义。例如:inta;//在标C中为声明,是不可执行语句;在C++中为定义,是可执行语句extern int a;//为声明,是不可执行语句 CWinAppcurApp;//对象定义是可执行语句◆使用内联函数时应注意以下几个问题:(1) 在一个文件中定义的内联函数不能在另一个文件中使用。它们通常放在头文件中共享。(2) 内联函数应该简洁,只有几个语句,如果语句较多,不适合于定义为内联函数。(3) 内联函数体中,不能有循环语句、if语句或switch语句,否则,函数定义时即使有inline关键字,编译器也会把该函数作为非内联函数处理。(4) 内联函数要在函数被调用之前声明。例如:#include <iostream.h>int increment(int i);inline int increment(int i){i++; return i;}void main(void){……}如果我们修改一下程序,将内联函数的定义移到main()之后:#include <iostream.h>int increment(int i);void main(void){……}//内联函数定义放在main()函数之后inline int increment(int i){i++; return i;}内联函数在调用之后才定义,这段程序在编译的时候编译器不会直接把它替换到main中。也就是说实际上"increment(int i)"只是作为一个普通函数被调用,并不具有内联函数的性质,无法提高运行效率。

3 volatile

获致幸福的不二法门是珍视你所拥有的遗忘你所没有的

static inline volatile的作用

相关文章:

你感兴趣的文章:

标签云: