C语言volatile、extern、auto、register的作用

来源:互联网 发布:京东店铺怎么优化 编辑:程序博客网 时间:2024/05/20 12:22

一、volatile

1、volatile关键字的含义

volatile提醒编译器,它后面所定义的变量的值随时都有可能改变,因此编译后的程序每次需要存储或读取这个变量的时候,都会直接从变量地址中读取数据。

如果没有volatile关键字,则编译器可能优化读取和存储,可能暂时使用寄存器中的值,如果这个变量由别的程序更新了的话,将出现不一致的现象

2、volatile关键字的使用场景

1)中断服务程序中修改的供其它程序检测的变量需要加volatile;

2)多任务环境下各任务间共享的标志应该加volatile;

3)存储器映射的硬件寄存器通常也要加volatile说明,因为每次对它的读写都可能由不同意义;

3、其他

volatile总是与优化有关,编译器有一种技术叫做数据流分析,分析程序中的变量在哪里赋值、在哪里使用、在哪里失效,分析结果可以用于常量合并,常量传播等优化,进一步可以死代码消除。但有时这些优化不是程序所需要的,这时可以用volatile关键字禁止做这些优化,volatile的字面含义是易变的,它有下面的作用

1)不会在两个操作之间把volatile变量缓存在寄存器中。在多任务、中断、甚至setjmp环境下,变量可能被其他的程序改变,编译器自己无法知道,volatile就是告诉编译器这种情况。

2)不做常量合并、常量传播等优化

3)对volatile变量的读写不会被优化掉。如果你对一个变量赋值但后面没用到,编译器常常可以省略那个赋值操作

二、extern

1、extern使用方式

extern可以置于变量或者函数前,以标示变量或者函数的定义在别的文件中,提示编译器遇到此变量和函数时在其他模块中寻找其定义。

此外extern也可用来进行链接指定

2、可以引用那些类型的数据

调用其他.c文件中的全局变量和非静态函数

三、auto

auto在C++98中的标识临时变量的语义,由于使用极少且多余,在C++11中已被删除

c++ 11中的auto主要有一下作用:

1、自动类型推断

// auto a; // 错误,没有初始化表达式,无法推断出a的类型 // auto int a = 10; // 错误,auto临时变量的语义在C++11中已不存在, 这是旧标准的用法// 1. 自动帮助推导类型 auto a = 10; auto c = 'A'; auto s("hello"); 

2、解决类型冗长

map<int, map<int,int> > map_; map<int, map<int,int>>::const_iterator itr1 = map_.begin(); const auto itr2 = map_.begin(); 

3、使用模板技术时,如果某个变量的类型依赖于模板参数

// 不使用auto将很难确定变量的类型(使用auto后,将由编译器自动进行确定)。 template <class T, class U> void Multiply(T t, U u) { auto v = t * u; } 

4、和decltype配合使用,返回值占位符

template <typename T1, typename T2> auto compose(T1 t1, T2 t2) -> decltype(t1 + t2) { return t1+t2; } auto v = compose(2, 3.14); // v's type is double 

四、register

1、register:这个关键字请求编译器尽可能的将变量存在CPU内部寄存器中,而不是通过内存寻址访问,以提高效率。注意是尽可能,不是绝对。

2、register修饰符暗示编译程序相应的变量将被频繁地使用,如果可能的话,应将其保存在CPU的寄存器中,以加快其存储速度

首先,register变量必须是能被CPU所接受的类型。这通常意味着register变量必须是一个单个的值,并且长度应该小于或者等于整型的长度。不过,有些机器的寄存器也能存放浮点数。

其次,因为register变量可能不存放在内存中,所以不能用“&”来获取register变量的地址。

由于寄存器的数量有限,而且某些寄存器只能接受特定类型的数据(如指针和浮点数),因此真正起作用的register修饰符的数目和类型都依赖于运行程序的机器,而任何多余的register修饰符都将被编译程序所忽略。

在某些情况下,把变量保存在寄存器中反而会降低程序的运行速度。因为被占用的寄存器不能再用于其它目的;或者变量被使用的次数不够多,不足以装入和存储变量所带来的额外开销。

早期的C编译程序不会把变量保存在寄存器中,除非你命令它这样做,这时register修饰符是C语言的一种很有价值的补充。然而,随着编译程序设计技术的进步,在决定那些变量应该被存到寄存器中时,现在的C编译环境能比程序员做出更好的决定。实际上,许多编译程序都会忽略register修饰符,因为尽管它完全合法,但它仅仅是暗示而不是命令

0 0