c++编程之关键字

c++关键字——typedef  auto  extern  static mutable   register  volatile  


typedef使用

typedef作用是数据类型定义新名字,或者简化一些比较复杂的类型声明。

1、c语言常见,用 pNode 代替 struct tagNode*

typedef struct tagNode
{
char* pItem;
pNode pNext;
}*pNode;
2、数据类型定义

typedef int byte_4;

     在不同平台数据类型字节不同,使用byte_4来代表4字节数据,移植时只需要修改typedef int byte_4;来实现4字节的定义即可,不需要全部修改。

3、定义指针

//#define char* char_ptr;
typedef char* char_ptr;
char_ptr a, b;
如果用define定义,替换为 char* a,b;   用typedef则表示  char *a,*b;

4、typedef & 复杂的变量声明

       从变量名看起,先往右,再往左,碰到一个圆括号就调转阅读的方向;括号内分析完就跳出括号,还是按先右后左的顺序,如此循环,直到整个声明分析完。然后把需要使用的替换即可!!!

分析三个:

int *(*a[5])(int, char*);

void (*b[10]) (void (*)());

doube(* (*pa)[9])();


int *(*a[5])(int, char*);    //a[5]是指针数组,指向函数,函数返回int*,函数参数为 int与char* 。

把a[5]替换即可,如下:

typedef   int *(*Pfunc)(int,char *);

Pfunc a[5];


void (*b[10]) (void (*)());//指针数组,指向函数;函数的参数为void (*)()

最直接的,替换b[10]

typedef  void (*Pfunc) (void (*)());

Pfunc a[5];

也可以进行两次替换

typedef  void (*Pfunc0)();

typedef  void (*Pfunc) (Pfunc0);


doube(* (*pa)[9])(); 

最直接的,替换 pa

typedef doube(* (*ptr)[9])();

也可以进行替换

typedef  doube(*Pfunc)();

typedef  Pfunc(*ptr)[9];


auto使用

auto是一种默认使用关键字,一般为默认使用,int a;其实就是 auto int a;


extren使用

extern置于变量或函数前,表示变量或者函数的定义在别的文件中,提示编译器遇到此变量或函数时,在其它模块中寻找其定义。extern也可用来进行链接指定。

源文件定义数组char a[6];在另一个文件进行声明:extern char *a; ———— 非法访问

指向a的指针并不是数组a。从 sizeof(a)可以看出,数组a大小为6;指针a大小为4(指针是int型,在32位系统为4字节),应改为extern char a[];

一个c文件想使用另一个c文件的全局变量或fun,则需要在它们共有的h文件中使用extern

C++在编译的时候为了解决函数的多态问题,会将函数名和参数联合起来生成一个中间的函数名称,而C语言则不会,因此会造成链接时找不到对应函数的情况,此时C函数就需要用extern “C”进行链接指定,这告诉编译器,请保持我的名称,不要给我生成用于链接的中间函数名。做法如下:

//在.h文件的头上
#ifdef __cplusplus
#if __cplusplus
extern "C"{
#endif
#endif /* __cplusplus */
…
…
//.h文件结束的地方
#ifdef __cplusplus
#if __cplusplus
}
#endif
#endif /* __cplusplus */


在遇到c++调用c文件函数的时候,统一编译是十分必要的。如下操作
test01.h

extern "C" int foo(int x, int y);

test01.cpp

int main(){int a = foo(2, 3);}

编译报错! ———— 错误 error LNK2001: 无法解析的外部符号 _foo

总结:

1、外部引用

2、 c/c++混合编程时,extern "C"标识


static 使用

1、静态全局变量
       静态全局变量在声明它的整个文件都是可见的,而在文件之外是不可见的。作用就是防止被外部文件使用
       <在函数体内声明的变量的值是随机的,除非它被显式初始化,而在函数体外被声明的变量也会被初始化为0>;未经初始化的静态变量会被程序自动初始化为0(无论是全局的还是局部的)

2、静态局部变量
静态局部变量有以下特点:
始终驻留在进程的数据区(函数结束不会被回收),直到程序结束。但其作用域为局部作用域,当定义它的函数或语句块结束时,其作用域随之结束。作用是保持不被栈回收,可被多线程调用共享。
静态局部变量一般在声明处初始化,如果没有显式初始化,会被程序自动初始化为0;

3、静态函数
       静态函数不能被其它文件所用。作用与静态全局变量作用相同

4、静态class数据成员
       在类内数据成员的声明前加上关键字static,该数据成员就是类内的静态数据成员,静态数据成员只分配一次内存,供所有对象共用。<它属于class本身,不属于任何一个对象>

5、静态class函数
        通常情况下,this 是缺省的,如函数fn() 实际上是this->fn() ,但是静态成员函数不与任何对象相联系,它不具有this指针。从这个意义上讲,它无法访问属于类对象的非静态数据成员,也无法访问非静态成员函数。


mutable使用

        C++中,mutable也是为了突破const的限制而设置的。被mutable修饰的变量,将永远处于可变的状态,即使在一个const函数中。当需要在const的函数里面修改一些跟类状态无关的数据成员,那么这个数据成员就应该被mutalbe来修饰。


volatile使用

       volatile是一个类型修饰符。表示其修饰的数据变量是易变的,应从内存中读取数据进行操作。这种特性,是为了满足多线程同步、中断、硬件编程等特殊需要(更多的使用在底层和多线程中)

根据局部性性能优化原则,进程的局部数据可存储在寄存器中,操作完成之后写回内存,这种优化在单线程的程序中没有问题,但到了多线程程序中,由于多个线程是并发运行的,就有可能一个线程把某个公共的变量已经改变了,其余线程仍然从寄存器取已过时的数据,就导致程序出现未知错误。

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


register使用

        register修饰符暗示变量将被频繁地使用,如果可能的话,应将其保存在CPU的寄存器中,以加快其存储速度。
   
使用register修饰符有几点限制:
  1、register变量必须是能被CPU所接受的类型。这通常意味着register变量必须是一个单个的值,并且长度应该小于或者等于整型的长度。(有些机器的寄存器也能存放浮点数,视情况而定)
  2、register变量可能不存放在内存中,所以不能用“&”来获取register变量的地址。
  3、由于寄存器的数量有限,并不是用register修饰的变量就一定会存储在寄存器中,任何多余的register修饰符都将被编译程序所忽略。
  4、在某些情况下,把变量保存在寄存器中反而会降低程序的运行速度。因为被占用的寄存器不能再用于其它目的;或者变量被使用的次数不够多,不足以装入和存储变量所带来的额外开销(寄存器中定义的变量需要进行维护与管理,有额外开销)。











猜你喜欢

转载自blog.csdn.net/ly601579033/article/details/52413172