C++ 在c++;内存写入可以通过优化来延迟吗?还是我需要易失性?

C++ 在c++;内存写入可以通过优化来延迟吗?还是我需要易失性?,c++,volatile,C++,Volatile,我在这里已经阅读了几十个关于volatile使用的问题和答案,我很抱歉发布了另一个问题和答案,但我认为我还没有看到我想要的东西 我有一个用C++编写的用于ARDUINO单片机的库。我有一个ISR,它填充一个缓冲区,当它完成时,它会设置一个标志,让外部世界知道有可用的数据。我有一个缓冲区,一个变量告诉缓冲区中有多少字节,还有一个标志告诉世界缓冲区中有数据。一旦我在ISR中设置了“我已完成填充缓冲区”标志,ISR将不会再次更改缓冲区或其长度,直到/除非我重新启用 通常,我将标志、缓冲区和长度值都声明

我在这里已经阅读了几十个关于volatile使用的问题和答案,我很抱歉发布了另一个问题和答案,但我认为我还没有看到我想要的东西

我有一个用C++编写的用于ARDUINO单片机的库。我有一个ISR,它填充一个缓冲区,当它完成时,它会设置一个标志,让外部世界知道有可用的数据。我有一个缓冲区,一个变量告诉缓冲区中有多少字节,还有一个标志告诉世界缓冲区中有数据。一旦我在ISR中设置了“我已完成填充缓冲区”标志,ISR将不会再次更改缓冲区或其长度,直到/除非我重新启用

通常,我将标志、缓冲区和长度值都声明为volatile,因为这是ISR例程中应该执行的操作

然而,一旦缓冲区满了,我就会对其进行大量处理,这意味着我在欺骗自己,使自己无法进行一些潜在的优化。在我的ISR之外,如果我有这样的代码

if (flag== FINISHED) {
  disable_my_ISR (); 
   /*do a bunch of stuff with the buffer*/
  reenable_my_ISR();
}
然后理论上我认为我不需要像易失性那样使用缓冲区。对吗?正如我所说,我担心的是我的“用缓冲区做一大堆事情”没有得到优化,因为缓冲区是不稳定的


我在这个论坛上看到的唯一的另一个答案是,我不确定这是否真的是相同的情况。

当你将某个东西标记为volatile时,你是说它的值可能会在代码中的写入/读取之间发生变化。这正是ISR访问变量时可能发生的情况,因此需要
volatile

您的ISR和主代码之间共享的任何变量都应该是volatile。您的代码可能在不标记所有内容的情况下工作,但它最终会咬到您

然后理论上我认为我不需要像易失性那样使用缓冲区


不,如果主代码和ISR都使用缓冲区,则需要将其标记为volatile。我认为您可能太担心缺少优化了。您始终可以将
volatile
数组复制到普通数组中,进行处理,并对差异进行计时。

优化甚至不会延迟内存写入-如果未声明缓冲区
volatile
,编译器可能会删除使用它的任何代码。举个例子:

int myBuffer[5] = {0};
if(flag == FINISHED) {
    printf("%d", myBuffer[0]);
}

即使您的ISR更改了缓冲区的值,这也很可能总是打印
0
,因为编译器不知道ISR如何更改程序流,因此假定
myBuffer[0]
在使用时将为0。

I可能是过度复杂的示例。如果我保证我的外部代码只在ISR被禁用时访问缓冲区,那么我的主张是,即使经验法则是“任何ISR内部和外部访问的所有内容都应该是易变的”在我的情况下,我保证我只在ISR禁用时访问缓冲区。为了继续我的解释…作为一个实现问题,我将保持ISR处于活动状态。它的一个版本在定时器上,另一个版本是引脚更改中断。但是,即使硬件中断仍然处于启用状态,我的ISR实际上什么也没做,因为我设置了一个标志,告诉它“不要做任何事情,就好像你被禁用了一样,如果设置了这个标志,就立即退出”。至于将数据复制到单独的缓冲区,Arduino微控制器通常只有大约2K的RAM内存,因此这不是一个选项。你说“当你将某个东西标记为易失性时,你是说它的值可能会在代码中的写入/读取之间发生变化。”我是说,尽管事实上存在ISR,我正在使用我自己的方法来确保在ISR之外永远不会访问数据,而ISR可能会对其进行更改。如果缓冲区对整个程序是全局的,那么您给出的示例代码是否仍然正确?我可以看到,如果我在函数中声明一个缓冲区,并在函数中使用该缓冲区进行操作,编译器应该可以自由地假设它知道我使用该缓冲区所做的一切。我想我在最初的问题中忽略了提到缓冲区对于整个模块是全局的。我应该补充一点,这个缓冲区对于整个程序是全局的。此外,这是一个单处理器环境。没有同步线程。我意识到线程和volatile之间并没有太多关系。线程作为一个整体另一个怪物:-)