编译器优化

volatile的作用

核能气质少年 提交于 2020-01-13 02:57:33
volatile关键字是一种类型修饰符,用它声明的类型变量表示可以被某些编译器未知的因素更改,比如:操作系统、硬件或者其它线程等。遇到这个关键字声明的变量,编译器对访问该变量的代码就不再进行优化,从而可以提供对特殊地址的稳定访问。   使用该关键字的例子如下:   int volatile nVint;   >>>>当要求使用volatile 声明的变量的值的时候,系统总是重新从它所在的内存读取数据,即使它前面的指令刚刚从该处读取过数据。而且读取的数据立刻被保存。   例如:   volatile int i=10;   int a = i;   ...   //其他代码,并未明确告诉编译器,对i进行过操作   int b = i;   >>>>volatile 指出 i是随时可能发生变化的,每次使用它的时候必须从i的地址中读取,因而编译器生成的汇编代码会重新从i的地址读取数据放在b中。而优化做法是,由于编译器发现两次从i读数据的代码之间的代码没有对i进行过操作,它会自动把上次读的数据放在b中。而不是重新从i里面读。这样以来,如果i是一个寄存器变量或者表示一个端口数据就容易出错,所以说volatile可以保证对特殊地址的稳定访问。   >>>>注意,在vc6中,一般调试模式没有进行代码优化,所以这个关键字的作用看不出来。下面通过插入汇编代码,测试有无volatile关键字

使用gcc编译C程序

℡╲_俬逩灬. 提交于 2020-01-12 20:14:16
GCC 全称"GNU C Compiler",不过自从面世后,增加了多种语言的支持,不过用的最多的是还是编译C或C++程序(另外有个工具叫做G++)。GCC是一种多目标编译器,通过可交互的后端处理器,为多种计算机架构生成可执行程序。 话说回来,什么是编译器呢? 编译器并不是一个单一的程序,它们通常由六七个稍小的程序组成,这些程序由一个叫做“编译器驱动器(Compiler driver)"的控制程序调用。 编译器一般由以下几部分组成: 预处理器(preprocessor) 语法和语义检查器(syntactic and semantic checker) 代码生成器(code generator) 汇编程序(assembler) 优化器(optimizer) 链接器(linker) 链接器确认main函数的初始进入点(程序开始执行的地方),把符号引用(symbolic reference)绑定到内存地址,把所有的目标文件集中到一起,再加上库文件,从而产生可执行文件。 本文主要介绍使用GCC编译C程序,不过GCC不支持C语言的许多“方言”,目前一般使用命令行参数 -std=c99 指定编译器支持C99标准。GCC对C11的标准支持是不完整的,尤其是涉及定义在头文件<threads.h>中的多线程函数。这是因为GCC的C链接库长期以来支持POSIX标准的多线程功能

C中的volatile用法

梦想的初衷 提交于 2020-01-11 07:57:52
C中的volatile用法 volatile 影响编译器编译的结果,指出,volatile 变量是随时可能发生变化的,与volatile变量有关的运算,不要进行编译优化,以免出错,(VC++ 在产生release版可执行码时会进行编译优化,加volatile关键字的变量有关的运算,将不进行编译优化。)。 例如: volatile int i=10; int j = i; ... int k = i; volatile 告诉编译器i是随时可能发生变化的,每次使用它的时候必须从i的地址中读取,因而编译器生成的可执行码会重新从i的地址读取数据放在k中。 而 优化做法是,由于编译器发现两次从i读数据的代码之间的代码没有对i进行过操作,它会自动把上次读的数据放在k中。而不是重新从i里面读。这样以来,如果 i是一个寄存器变量或者表示一个端口数据就容易出错,所以说volatile可以保证对特殊地址的稳定访问,不会出错。 /********************** 一个定义为volatile的变量是说这变量可能会被意想不到地改变,这样,编译器就不会去假设这个变量的值了。精确地说就是,优化器在用到这个变量时必须每次都小心地重新读取这个变量的值,而不是使用保存在寄存器里的备份。下面是volatile变量的几个例子: 1) 并行设备的硬件寄存器(如:状态寄存器) 2)

C中的volatile用法

女生的网名这么多〃 提交于 2020-01-09 00:29:50
.volatile的本质: 1> 编译器的优化 在本次线程内, 当读取一个变量时,为提高存取速度,编译器优化时有时会先把变量读取到一个寄存器中;以后,再取变量值时,就直接从寄存器中取值;当变量值在本线程里改变时,会同时把变量的新值copy到该寄存器中,以便保持一致。 当变量在因别的线程等而改变了值,该寄存器的值不会相应改变,从而造成应用程序读取的值和实际的变量值不一致。 当该寄存器在因别的线程等而改变了值,原变量的值不会改变,从而造成应用程序读取的值和实际的变量值不一致。 2>volatile应该解释为“直接存取原始内存地址”比较合适,“易变的”这种解释简直有点误导人。 volatile 影响编译器编译的结果,指出,volatile 变量是随时可能发生变化的,与volatile变量有关的运算,不要进行编译优化,以免出错,(VC++ 在产生release版可执行码时会进行编译优化,加volatile关键字的变量有关的运算,将不进行编译优化。)。 例如: volatile int i=10; int j = i; ... int k = i; volatile 告诉编译器i是随时可能发生变化的,每次使用它的时候必须从i的地址中读取,因而编译器生成的可执行码会重新从i的地址读取数据放在k中。 而 优化做法是,由于编译器发现两次从i读数据的代码之间的代码没有对i进行过操作

第一周 ch01 课下测试

[亡魂溺海] 提交于 2020-01-09 00:08:51
1.Amdahl定律说明,我们对系统的某个部分做出重大改进,可以显著获得一个系统的加速比。(B) A .正确 B .错误 解析:Amdahl定律,该定律的主要思想是,当我们对系统的某个部分加速时,其对整个性能的影响取决于该部分的重要性和加速程度。 2.Linux中,内核虚拟内存在虚拟地址空间的低端。(B) A . 正确 B . 错误 解析:由上图可知内核虚拟内存在虚拟地址空间的最顶端而不是最低端 3.实现进程这个抽象概念需要低级硬件和操作系统软件之间的紧密合作。(A) A . 正确 B . 错误 解析:进程是操作系统对正在运行的程序的一种抽象。一个系统上可以同时运行多个进程,每个进程好像独占的使用硬件。所谓并发,是说一个进程的指令和另一个进程的指令交错执行。操作系统实现这种交错执行的机制称为上下文切换。操作系统跟踪进程运行所需的所有状态信息(也就是上下文),任何一个时刻,处理器只能运行一个进程。当操作系统决定要把控制权从当前进程转移到一个新进程时,就要进行上下文切换,即保存当前进程的上下文,恢复新进程的上下文,然后将控制权转交给新进程,新进程就从上次停止的地方开始执行。实现进程这个抽象概念需要低级硬件和操作系统软件之间的紧密合作 4.操作系统有两个基本功能:防止硬件被滥用;向应用供一致的机制来控制低级硬件设备。实现这两个功能相关的抽象有(ACD) A . 文件 B . 虚拟机 C

C语言volatile关键字的用法

ぐ巨炮叔叔 提交于 2020-01-08 18:25:21
作用 编辑 简单地说就是防止编译器对代码进行优化。比如如下程序: 1 2 3 4 XBYTE[2]=0x55; XBYTE[2]=0x56; XBYTE[2]=0x57; XBYTE[2]=0x58; 对外部硬件而言,上述四条语句分别表示不同的操作,会产生四种不同的动作,但是编译器却会对上述四条语句进行优化,认为只有XBYTE[2]=0x58(即忽略前三条语句,只产生一条机器代码)。如果键入 volatile ,则编译器会逐一地进行编译并产生相应的机器代码(产生四条代码)。 例子 编辑 精确地说就是,编译器在用到这个变量时必须每次都小心地重新读取这个变量的值,而不是使用保存在 寄存器 里的备份。下面是volatile变量的几个例子: 1)并行设备的硬件寄存器(如:状态寄存器) 2)一个中断服务子程序中会访问到的非自动变量(Non-automatic variables) 3)多线程应用中被几个任务共享的变量 这是区分C程序员和 嵌入式系统 程序员的最基本的问题:嵌入式系统程序员经常同硬件、中断、RTOS等等打交道,所有这些都要求使用volatile变量。不懂得volatile内容将会带来灾难。 假设被面试者正确地回答了这个问题(嗯,怀疑是否会是这样),我将稍微深究一下,看一下这家伙是不是真正懂得volatile完全的重要性。 1)一个参数既可以是const还可以是volatile吗

详解C中volatile关键字

我们两清 提交于 2020-01-08 08:28:00
volatile提醒编译器它后面所定义的变量随时都有可能改变,因此编译后的程序每次需要存储或读取这个变量的时候,都会直接从变量地址中读取数据。如果没有volatile关键字,则编译器可能优化读取和存储,可能暂时使用寄存器中的值,如果这个变量由别的程序更新了的话,将出现不一致的现象。下面举例说明。在DSP开发中,经常需要等待某个事件的触发,所以经常会写出这样的程序: short flag; void test() { do1(); while(flag==0); do2(); } 这段程序等待内存变量flag的值变为1(怀疑此处是0,有点疑问,)之后才运行do2()。变量flag的值由别的程序更改,这个程序可能是某个硬件中断服务程序。例如:如果某个按钮按下的话,就会对DSP产生中断,在按键中断程序中修改flag为1,这样上面的程序就能够得以继续运行。但是,编译器并不知道flag的值会被别的程序修改,因此在它进行优化的时候,可能会把flag的值先读入某个寄存器,然后等待那个寄存器变为1。如果不幸进行了这样的优化,那么while循环就变成了死循环,因为寄存器的内容不可能被中断服务程序修改。为了让程序每次都读取真正flag变量的值,就需要定义为如下形式: volatile short flag; 需要注意的是,没有volatile也可能能正常运行

[转帖]思维导图学Java虚拟机(修订版)

我只是一个虾纸丫 提交于 2020-01-08 07:44:33
思维导图学Java虚拟机(修订版) https://www.zybuluo.com/Yano/note/645642 简书 说明 第二次读周志明的《深入理解Java虚拟机》,感觉我原来的思维导图笔记,在结构上有些问题。更改了GC、虚拟机字节码执行引擎、Java编译器与代码优化等内容~ 原思维导图链接: 思维导图学Java虚拟机 Java 与 C/C++ 的编译器对比 目录 走进Java 自动内存管理机制 内存区域 GC JVM监控工具 虚拟机字节码执行引擎 执行引擎 字节码 类加载 Java编译器与代码优化 前端编译器 JIT编译器(Just In Time) AOT编译器(Ahead Of Time) 高效并发 来源: https://www.cnblogs.com/jinanxiaolaohu/p/12159511.html

stdio.h及cstdio的区别

 ̄綄美尐妖づ 提交于 2020-01-08 06:02:52
2013-07-04 16:45:19 找了很多资料,没有说的很明白的,下面是老外的一篇文章,解释的比较清楚,后面给出翻译。 Clarifying stdio.h versus cstdio 转自: http://forums.codeguru.com/showthread.php?344430-Clarifying-stdio-h-versus-cstdio I constantly see recommendations to #include <cstdio> instead of using stdio.h and the same for the other C headers. What most posters fail to mention is that this should put all the symbols into namespace std and NOT into the global namespace. This you have to write std::printf(...). Simply writing printf alone will not work . The same applies to the headers : cassert ciso646 csetjmp cstdio ctime cctype climits

编译到底做了什么(***.c -> ***.o的过程)

风格不统一 提交于 2020-01-08 04:32:42
(第一次写博客,好激动的说.......) 我们知道,一个程序由源代码到可执行文件往往由这几步构成: 预处理(Prepressing)-> 编译(Compilation)-> 汇编(Assembly)-> 链接(Linking)。 编译过程就是把预处理完的文件进行一系列词法分析、语法分析、语义分析及优化后生产相应的汇编代码文件,这个过程往往是我们所说的整个程序构建的核心部分。那么,这个核心部分究竟做了什么呢。 各位看官容我挽起袖子,且听我娓娓道来。 编译器做了什么? 从最直观的角度来说,编译器就是将高级语言翻译成机器语言的一个工具。 以 C语言为例,解释一下 ***.c -> ***.o 的过程。 假设test.c有下面一段代码 array[index] = (index + 4) * (2 + 6); 下面就来谈谈这个表达式是如何翻译成机器语言的过程。 这个过程主要有如下五步,看起来好长的样子,看官需静下心来慢慢看。。。。 1.词法分析 -- 将源代码字符序列分割成一系列的记号 源代码程序被输入到扫描器(Scanner)。 扫描器的任务就是:运用一种有限状态机(Finite State Machine)的算法,将源代码字符序列分割成一系列的记号(Token)。还有一些其他工作(将标识符放到符号表,将数字、字符串放到文字表中) 如下图(因为表格换页了,所以拍出来是这个样子,望海涵)