当前位置: 首页 > 知识库问答 >
问题:

-o0编译器标志是否与C语言中的volatile关键字具有相同的效果?

孔星宇
2023-03-14
    null

缺点:

  • -o0标志将影响整个代码,而volatile关键字只影响特定变量。例如,如果我们在一个小型微控制器上工作,这可能是一个问题,因为使用-o0可能会产生一个大的可执行文件。

共有1个答案

都沈浪
2023-03-14

简单的回答是:volatile关键字并不意味着“不优化”。这是完全不同的东西。它通知编译器,变量可能被一些在正常程序流中编译器不可见的东西所改变。例如:

  1. 它可以由硬件更改--通常是映射在内存地址空间中的寄存器
  2. 可以通过从未调用的函数更改-例如中断例程
  3. 变量可以由另一个进程或硬件更改-例如多处理器/多核系统中的共享内存

每次使用volatile变量时都必须从其存储位置读取volatile变量,并在每次更改时保存该变量。

int foo(volatile int z)
{
    return z + z + z + z;
}

int foo1(int z)
{
    return z + z + z + z;    
}
foo(int):
  push rbp
  mov rbp, rsp
  mov DWORD PTR [rbp-4], edi
  mov edx, DWORD PTR [rbp-4]
  mov eax, DWORD PTR [rbp-4]
  add edx, eax
  mov eax, DWORD PTR [rbp-4]
  add edx, eax
  mov eax, DWORD PTR [rbp-4]
  add eax, edx
  pop rbp
  ret
foo1(int):
  push rbp
  mov rbp, rsp
  mov DWORD PTR [rbp-4], edi
  mov eax, DWORD PTR [rbp-4]
  sal eax, 2
  pop rbp
  ret

我想差别是很明显的。volatile变量读4次,nonvolatile变量读一次,然后乘以4。

你可以在这里玩自己:https://godbolt.org/g/ritu4G

在大多数情况下,如果当您打开编译器优化时程序没有运行,那么您的代码中有一些隐藏的UBs。您应该根据需要进行调试,以发现所有这些错误。正确编写的程序必须在任何优化级别上运行。

 类似资料:
  • Volatile关键字 Volatile就是防优化。Volatile一般和硬件有关,指向硬件的内容可能我们需要不要让编译器去优化,每次都要读取那里的内容。比如我们在实际操作中有一个键盘,我们查看一个按键是否被按下,就是通过读取内存里面关于按键状态的高低电平来识别。那么我们怎么来读取这一个位里面的状态(0或1)?我们能够访问到最小的内存地址就是一个字节,而一个字节里面有8个位。所以我们只能利用一个u

  • Joe Albahari有一个很棒的多线程系列,这是必读的,任何做C#多线程的人都应该熟记于心。 然而,在第4部分中,他提到了volatile的问题: 请注意,应用volatile并不能阻止先写后读的交换,这可能会产生脑筋急转弯。Joe Duffy用下面的例子很好地说明了这个问题:如果Test1和Test2同时在不同的线程上运行,那么a和b的值都可能为0(尽管在x和y上都使用volatile) 然

  • 问题内容: 我知道Java本身没有直接的等效项,但也许是第三方? 真的很方便。当前,我想实现一个迭代器,该迭代器生成树中的所有节点,这大约是带有yield的五行代码。 问题答案: 我知道的两个选项是2007年的Aviad Ben Dov的infomancers- collections库 和2008年的Jim Jimler的YieldAdapter库 (在另一个答案中也提到了)。 两者都允许您使用

  • 安装编译器或者 IDE(集成开发环境),也叫搭建开发环境。Windows 下的C语言 IDE 众多,多如牛毛,初学者往往不知道该如何选择,本节就来给大家指点迷津。 1) Visual Studio Windows 下首先推荐大家使用微软开发的 Visual Studio(简称 VS),它是 Windows 下的标准 IDE,实际开发中大家也都在使用。为了适应最新的 Windows 操作系统,微软每

  • 问题内容: 来自C和C ++背景,我发现明智地使用typedef会带来极大帮助。您是否知道在Java中实现类似功能的方法,无论是Java机制,模式还是您使用的其他有效方法? 问题答案: Java具有原始类型,对象和数组,仅此而已。没有typedef。

  • 主要内容:关键字,标识符Go语言的词法元素包括 5 种,分别是标识符(identifier)、关键字(keyword)、操作符(operator)、分隔符(delimiter)、字面量(literal),它们是组成Go语言代码和程序的最基本单位。 本节我们主要来介绍一下Go语言中的关键字和标识符。 关键字 关键字即是被Go语言赋予了特殊含义的单词,也可以称为保留字。 Go语言中的关键字一共有 25 个: break de