为了成功上岸之C语言关键字总结

static关键字的作用

  1. 函数体内static变量的作用范围为该函数体,不同于auto变量,该变量的内存只被分配一
    次,因此其值在下次调用时仍维持上次的值;
  2. 在模块内的static全局变量可以被模块内所有函数访问,但不能被模块外其它函数访问;
  3. 在模块内的static函数只可被这一模块内的其它函数调用,这个函数的使用范围被限制在
    声明它的模块内;这样的好处是,不用担心被其他模块内的同名函数干扰;
  4. 在类中的static成员变量属于整个类所拥有,对类的所有对象只有一份拷贝;
  5. 在类中的static成员函数属于整个类所拥有,这个函数不接收this指针,因而只能访问类的
    static成员变量。

使用static与普通的区别

  1. static全局变量与普通的全局变量有什么区别:

static全局变量只初使化一次,防止在其他文件单元中被引用;

  1. static局部变量和普通局部变量有什么区别:

static局部变量只被初始化一次,下一次依据上一次结果值;

  1. static函数与普通函数有什么区别:

static函数在内存中只有一份,普通函数在每个被调用中维持一份拷贝

const关键字的作用

  1. 欲阻止一个变量被改变,可以使用const关键字。在定义该const变量时,通常需要对它进
    行初始化,因为以后就没有机会再去改变它了;
  2. 对指针来说,可以指定指针本身为const,也可以指定指针所指的数据为const,或二者同
    时指定为const;
  3. 在一个函数声明中,const可以修饰形参,表明它是一个输入参数,在函数内部不能改变
    其值;
  4. 对于类的成员函数,若指定其为const类型,则表明其是一个常函数,不能修改类的成员
    变量;
  5. 对于类的成员函数,有时候必须指定其返回值为const类型,以使得其返回值不为“左
    值”。
    例如:
    const classA operator*( const classA& a1, const classA& a2);
    opera operator* 的返回结果必须是一个const对象。
    如果不是,下面这样的变态代码也不会编译出错:
    classA a, b, c;
    (a * b) = c; // 对a*b的结果赋值
    操作(a * b) = c显然不符合编程者的初衷,也没有任何意义。

const在不同位置的含义

const int a; a是一个常整型数
int const a; a是一个常整型数
const int * a ; a是一个指向常整型数的指针,整型数是不可修改的,但指针可以
int * const a; a为指向整型数的常指针,指针指向的整型数可以修改,但指针是不可修改的
int const * a const; a是一个指向常整型数的常指针,指针指向的整型数是不可修改的,同时指针也是不可修改的

const常量和#define宏定义的区别

  1. 宏定义只是对值进行简单的替换,不进行类型检查;而const有具体的类型,在编译阶段会进行类型检查
  2. #define宏是在预处理阶段展开,而const常量在编译运行阶段
  3. const定义的常量在程序的运行过程中只有一份拷贝(因为是全局的只读变量,故存在静态区);而#define定义的常量在内存中有若干个拷贝
  4. const效率高,因为编译器通常不为普通const常量分配内存,而是保存在符号表中,没有了存储与读取的操作,效率很高
  5. 用define定义的常量是不可以用指针变量去指向的,用const定义的常量是可以用指针去指向该常量的地址的;
  6. 用define可以定义一些简单的函数(宏替换只作替换,不做计算,不做表达式求解),const 是不可以定义函数的;
  7. 宏定义的作用范围仅限于当前文件。而默认状态下, const 对象只在文件内有效,当多个文件中出现了同名的const变量时,等同于在不同文件中分别定义了独立的变量。如果想在多个文件之间共享const对象,必须在变量定义之前添加extern关键字(在声明和定义时都要加)。

extern关键字的理解

  1. 作用是用于修饰变量或函数,表明该变量或函数都是在别的文件中定义的,提示编译器在其他文件中寻找定义;
  2. 要注意头文件声明时加extern,定义是不要加,因为extern可以多次声明,但只有一个定义
  3. extern在链接阶段起作用

extern “C”的使用

在C++环境下使用C函数的时候,常常会出现编译器无法找到obj模块中的C函数定义,从而导致链接失败的情况,应该如何解决这种情况呢?
因为,C++语言在编译的时候为了解决函数的多态问题,会将函数名和参数联合起来生成一个中间的函数名称,而C语言则不会,因此会造成链接时找不到对应函数的情况,此时C函数就需要用extern “C”进行链接指定,这告诉编译器,请保持我的名称,不要给我生成用于链接的中间函数名。
所以extern “C”的作用在于C++代码中调用C库函数的声明,或C++中编译的函数要在C中调用。

volatile的作用

volatile的本意是“易变的” 。因为访问寄存器要比访问内存单元快的多,所以编译器一般都会作减少存取内存的优化,但有可能会读脏数据(编译器优化常用的方法有:将内存变量缓存到寄存器;调整指令顺序充分利用CPU指令流水线,常见的是重新排序读写指令)。当要求使用volatile声明变量值的时候,系统总是重新从它所在的内存读取数据,即使它前面的指令刚刚从该处读取过数据。精确地说就是,遇到volatile关键字声明的变量,编译器对访问该变量的代码就不再进行优化,从而可以提供对特殊地址的稳定访问;如果不使用valatile,则编译器将对所声明的语句进行优化。(简洁的说就是:volatile关键字是一种类型修饰符,用它声明的类型变量表示可以被某些编译器未知的因素更改,比如:操作系统、硬件或者其它线程等。遇到这个关键字声明的变量,编译器对访问该变量的代码就不再进行优化,从而可以提供对特殊地址的稳定访问。

volatile的使用

1. 并行设备的硬件寄存器(如:状态寄存器
  存储器映射的硬件寄存器通常要用volatile,因为每次对他的读写都有可能有不同的意义;相关寄存器定义时也会用到volatile,因为这些寄存器中的值是随时变化的,假设存在一个名叫AAA的寄存器,如果未用volatile修饰,那么在使用这个AAA寄存器的时候,会直接从CPU寄存器中取值,因为AAA寄存器之前被访问过,也就是之前就从内存中取出AAA的值保存到某个寄存器中,之所以直接从CPU寄存器中取值而不去内存中取值,是因为编译器优化代码的结果[访问CPU寄存器比访问RAM快得多]
2. 一个中断服务子程序中会访问到非自动变量
  由于访问寄存器比RAM快得多,所以编译器会做减少存取外部RAM的优化,从而导致一些值的变化脱离程序原本的设计意义
3. 多线程应用中被几个任务共享的变量
  当两个线程中都要用到某一个变量且该变量的值会被改变时,如果不用volatile修饰,很有可能会导致一个线程使用内存中的变量,另一个使用寄存器中的变量,显然,程序会出错。

volatile和const是否可以同时修饰一个变量

可以,const表示变量只读,也就是不希望该变量被本程序改变,但如果该变量可能被其他程序程序改变,而本程序还在检测这个变量的值,这时就需要加上volatile。此时,变量具备const和volatile的双重属性。例如:
  extern const volatile unsigned int rt_clock;
这是在RTOS系统内核中常见的一种声明:rt_clock通常是指系统时钟,它经常被时钟中断进行更新。所以它是volatile,因此在用的时候,要让编译器每次从内存里面取值。而rt_clock通常只有一个写者(时钟中断),其他地方对其的使用通常都是只读的。所以将其声明为 const,表示这里不应该修改这个变量。所以volatile和const是两个不矛盾的东西,并且一个对象同时具备这两种属性也是有实际意义的。
可以的,例如只读的状态寄存器。它是volatile因为它可能被意想不到地改变。它是const因为程序不应该试图去修改它。

一个指针可以是 volatile 吗

可以,当一个中断服务子程序修改一个指向一个buffer的指针时。例如:int* volatile ptr; 这里实际上是定义了一个int类型的指针,并且这个指针本身是volatile的,但是指针所指向的内容并不是volatile的,实际使用时,编译器对代码中指针变量ptr本身的操作不会进行优化,但是对ptr指向的内容却会作为non-volatile内容来处理,对*ptr的操作还是会被优化。这种写法一般出现在这个指针变量有可能会被中断函数修改的情形。将其定义为volatile以后,编译器每次取指针变量的值的时候都会从内存中载入,这样即使这个变量已经被别的程序修改了当前函数用的时候也能得到修改后的值。
可以,当一个中服务子程序修该一个指向一个buffer的指针时。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值