c/c 之常用关键字 -ag凯发k8国际
tips:
1. 本人当初学习c/c 的记录。
2. 资源很多都是来自网上的,如有ag凯发k8国际的版权请及时告知!
3. 可能会有些错误。如果看到,希望能指出,以此共勉!
c及c 中变量的存储方式有三种:自动、静态、动态。在c 11中,额外增加了一种:线程存储方式(关键字thread_local)。(c没有)以下所谓的可见并不是指编程者可以直接使用,这里的可见是对编译器/连接器来说的,它们在编译链接时能够发现其他文件中的变量。如果编程者要使用,还是必须显示声明。 c 标准使用翻译单元表示编译的单位,下面以文件为编译单元来说的。
自动类型:程序执行到其所属的函数或代码块时,才为其分配内存,直到其所属的函数或者代码块结束,内存就被释放了。
静态类型:在整个程序运行过程中都存在。
动态类型:从new开始一直到delete或者程序结束。
线程存储方式:与所属的线程同生命周期。
auto关键字
c中: auto关键字来源于c语言,唯一作用就是显示指明所定义的局部变量为自动存储类型(默认就是auto,常省略),而且auto只能用于修饰默认为自动存储类型的变量(意味着,想定义auto int a = 0; 的全局变量是不可以的),因此几乎没有人使用它。
c 中:但是从c 11开始,auto关键字有了全新的用法:自动判断数据类型,原来的用法被视为非法。注意:c 11中,auto的变量必须在定义时初始化。
如上例子中,变量a将自动判断为int型,因为其被赋值为整型10。
当然,auto关键字不仅仅是为了以上的简单情况,对于上面的情况来说,auto显得有点鸡肋。对于复杂情况,例如标准模块库(stl),自动判断才更有用。如下:
c 98中:
std::vector
std::vector
c 11中:
std::vector
auto pv = scores.begin(); // 自动判断,简化代码
register关键字
c中: register关键字最初由c语言引入,它建议编译器采用cpu的寄存器来存储指定的自动类型变量,旨在提高变量的访问速度。
c 中:其用来告诉编译器被其所修饰的局部变量使用频繁,编译器可以做特殊处理。
c 11开始:其作用只是显示指出定义的局部变量是自动存储类型,而且只能修饰原本就是自动类型的变量。这与auto关键字原来的用法完全相同。保留的唯一原因就是代码兼容。
mutable关键字
主要用于c 中:该关键字跟constant(既c 中的const)是反义词,用来指出即使结构体或者类为const类型,其成员只要被mutable修饰,值仍然可以被修改。该关键字只用在类中或者结构体中,用来修饰单个变量是不被允许的。
const关键字
默认情况下,全局变量的可见性是所有文件,但是被const修饰的全局变量却只在当前文件可见,和使用了static修饰一样。这样,在头文件中定义的const变量,在被多个文件包含时,不会再出现重复包含。
extern关键字
extern可以置于变量或者函数前,以标识变量或者函数的定义在别的文件中,提示编译器遇到此变量和函数时在其他模块中寻找其定义。extern也可用来进行链接指定。也就是说extern有两个作用:
extern “c” {
… // 代码
}
extern变量
extern用在变量声明中常常有这样一个作用,你在*.c文件中声明了一个全局的变量,这个全局的变量如果要被其他模块引用,使用前就要在使用的模块中用extern来声明。
在定义变量的时候,这个extern可以被省略(定义时,默认均省略);在声明变量的时候,这个extern必须添加在变量前。
定义和声明的区别:定义要为变量分配内存空间;而声明不需要为变量分配内存空间。定义只能一次,声明可多次
extern函数
由于函数的定义和声明是有区别的,定义函数要有函数体,声明函数没有函数体(还有以分号结尾),所以函数定义和声明时都可以将extern省略掉。关键字extern,仅仅是暗示这个函数可能在别的源文件里定义,没有其它作用。即下述两个函数声明没有区别:
extern int func(); 和int func(); // 等价
上例中,main函数中调用了b.c中定义的函数,只要在第一次使用之前声明了就可以。函数声明,不管在哪里(跨文件),都可以省略extern关键字。
extern与#include “*.h”的区别
static关键字
static变量
静态变量属于静态存储方式,其存储空间为内存中的静态数据区(在静态存储区内分配存储单元),该区域中的数据在整个程序的运行期间一直占用这些存储空间(在程序整个运行期间都不释放),也可以认为是其内存地址不变,直到整个程序运行结束(相反,动态局部变量,属于动态存储类别,占动态存储空间,函数调用结束后即释放)。静态变量虽在程序的整个执行过程中始终存在,但是在它作用域之外不能使用。
另外,属于静态存储方式的量不一定就是静态变量。 例如:外部变量虽属于静态存储方式,但不一定是静态变量,必须由 static加以定义后才能成为静态外部变量,或称静态全局变量。
静态局部变量:
函数内部的static变量同自动变量(即未加 static 声明的局部变量)一样,是某个特定函数的局部变量,即只能在定义该变量的函数内使用该变量,两者作用域相同;两者的不同在于:自动变量会随着函数被调用和退出而存在和消失,而static类局部变量不会,它不管其所在的函数是否被调用,都将一直存在;不过,尽管该变量还继续存在,但不能使用它。倘若再次调用定义它的函数时,它又可继续使用,而且保存了前次被调用后留下的值。换言之,static类型的内部变量是一种只能在某个特定函数中使用,但一直占据存储空间的变量。
函数体内如果在定义静态变量的同时进行了初始化,则以后程序不再进行初始化操作(出现在函数内部的基本类型的静态变量初始化语句只有在第一次调用才执行)。而对自动变量赋初值是在函数调用时进行,每调用一次函数重新给一次初值,相当于执行一次赋值语句。
静态局部变量的初始化表达式必须是一个常量或者常量表达式。即使局部静态变量定义时没有赋初值,系统会自动赋初值0(对数值型变量)或空字符(对字符变量);静态变量的初始值为0。而对自动变量来说,如果不赋初值则它的值将是个不确定的值。
当多次调用一个函数且要求在调用之间保留某些变量的值时,可考虑采用静态局部变量。虽然用全局变量也可以达到上述目的,但全局变量有时会造成意外的副作用,因此仍以采用局部静态变量为宜。
注:局部静态变量占用内存时间较长,并且可读性差,因此,除非必要,尽量避免使用局部静态变量。
静态全局变量
全局变量(外部变量)的说明之前再冠以static 就构成了静态的全局变量。全局变量本身就是静态存储方式,静态全局变量当然也是静态存储方式。这两者在存储方式上并无不同。这两者的区别在于:
非静态全局变量的作用域是整个源程序,当一个源程序由多个源文件组成时,非静态的全局变量在各个源文件中都是有效的。
静态全局变量则限制了其作用域,即只在定义该变量的源文件内有效,在同一源程序的其它源文件中不能使用它。
静态函数(又称内部函数)
c 和c一样,不允许一个函数中定义另一个函数,所以函数默认都是静态存储的。函数的定义和声明默认情况下是extern的。默认情况下,函数在程序执行的整个过程中都是存在的。其作用域为所有文件可见,这就要求多文件中不能定义同名函数。在函数的返回类型前加上关键字static,函数就被定义成为静态函数。静态函数只是在声明他的文件当中可见,不能被其他文件所用。定义静态函数的好处:
静态函数必须在第一次调用之前就被声明了,例如:头文件中声明没有加static,只是在定义中加了static,是没有用的!
类中的静态变量和函数
静态成员变量
对于非静态数据成员,每个类对象都有自己的拷贝。而静态数据成员被当作是类的成员。无论这个类的对象被定义了多少个,静态数据成员在程序中也只有一份拷贝,由该类型的所有对象共享访问。也就是说,静态数据成员是该类的所有对象所共有的。对该类的多个对象来说,静态数据成员只分配一次内存,供所有对象共用。所以,静态数据成员的值对每个对象都是一样的,它的值可以更新- 静态数据成员存储在全局数据区。静态数据成员定义时要分配空间,所以不能在类声明中定义。
- 静态数据成员和普通数据成员一样遵从public、protected、private访问规则。公共静态数据成员可被类的外部访问,保护或私有静态数据成员只可被类的内部访问
- 因为静态数据成员在全局数据区分配内存,属于本类的所有对象共享,所以,它不属于特定的类对象,在没有产生类对象时其作用域就可见,即在没有产生类的实例时,我们就可以操作它
- 静态数据成员初始化与一般数据成员初始化不同。静态数据成员初始化必须在类体外进行,而前面不加static,以免与一般静态变量或对象相混淆。格式为:
<数据类型><类名>::<静态数据成员名>=<值> - 类的静态数据成员有两种访问形式(访问权限允许的话):
<类对象名>.<静态数据成员名> 或 <类类型名>::<静态数据成员名> - 静态数据成员主要用在各个对象都有相同的某项属性的时候。
- 同全局变量相比,使用静态数据成员有两个优势:
- 静态数据成员没有进入程序的全局名字空间,因此不存在与程序中其它全局名字冲突的可能性
- 可以实现信息隐藏。静态数据成员可以是private成员,而全局变量不能
静态成员函数
与静态数据成员一样,我们也可以创建一个静态成员函数,它为类的全部服务而不是为某一个类的具体对象服务。静态成员函数与静态数据成员一样,都是类的内部实现,属于类定义的一部分。 普通的成员函数一般都隐含了一个this指针,this指针指向类的对象本身,因为普通成员函数总是具体的属于某个类的具体对象的。通常情况下,this 是缺省的。如函数func()实际上是this->func()。 与普通函数相比,静态成员函数由于不是与任何的对象相联系,因此它不具有this指针。从这个意义上讲,它无法访问属于类对象的非静态数据成员,也无法访问非静态成员函数,它只能调用其余的静态成员函数。关于静态成员函数,可以总结为以下几点:- 出现在类体外的函数定义不能指定关键字static,这一点尤为注意,很多时候在.h中定义类,在.cpp文件中写具体实现,这是的静态函数就不用static了。
- 静态成员之间可以相互访问,即:静态成员函数访问静态数据成员和访问静态成员函数
- 非静态成员函数可以任意地访问静态成员函数和静态数据成员
- 静态成员函数不能访问非静态成员函数和非静态数据成员
- 由于没有this指针的额外开销,因此静态成员函数与类的全局函数相比速度上会有少许的增长
- 不能将静态成员函数定义为虚函数。
- 调用静态成员函数,可以用成员访问操作符(.)和(->)为一个类的对象或指向类对象的指针调用静态成员函数,也可以直接使用如下格式:
<类名>::<静态成员函数名>(<参数表>)
volatile关键字
主要用于c语言,一个定义为volatile的变量是说这变量可能会被意想不到地改变,这样,编译器就不会去假设这个变量的值了。精确地说就是,优化器在用到这个变量时必须每次都小心地重新读取这个变量的值,而不是使用保存在寄存器里的备份。例如: volatile int i=10; int j = i; ... int k = i; 如果没有 volatile关键字,由于编译器发现两次从i读数据的代码之间的代码没有对i进行过操作,它会自动把上次读的数据放在k中。而不是重新从i里面读;而加了volatile后,每次都会重新读取i的值。 下面是volatile变量的几个常用方式:一个参数既可以是const还可以是 volatile。例如:一个例子是只读的状态寄存器。它是volatile因为它可能被意想不到地改变。它是const因为程序不应该试图去修改它
一个指针可以是volatile。一个例子是当一个中断服务子程序修改一个指向一个buffer的指针时。
总结
以上是ag凯发k8国际为你收集整理的c/c 之常用关键字的全部内容,希望文章能够帮你解决所遇到的问题。