C 如何安全地转换/复制易失性变量?

C 如何安全地转换/复制易失性变量?,c,volatile,C,Volatile,在上面的例子中,我得到了来自AVRCC编译器的警告 volatile char* sevensegment_char_value; void ss_load_char(volatile char *digits) { ... int l=strlen(digits); ... } ss_load_char(sevensegment_char_value); 所以我必须以某种方式将值从volatile复制到非volatile var?安全的解决方法是什么?编译器警

在上面的例子中,我得到了来自AVRCC编译器的警告

volatile char* sevensegment_char_value;

void ss_load_char(volatile char *digits) {
    ...
    int l=strlen(digits);
    ...
 }

 ss_load_char(sevensegment_char_value);

所以我必须以某种方式将值从volatile复制到非volatile var?安全的解决方法是什么?

编译器警告只意味着strlen()不会将指针视为易失性指针,即在计算字符串长度时,它可能会将指针缓存在寄存器中。我想,你没问题

通常,
volatile
表示编译器不会缓存变量。看看这个例子:

Warning 6   passing argument 1 of 'strlen' discards 'volatile' qualifier from pointer target type [enabled by default]
如果
flag!=0
,因为编译器假定该标志不会像其他线程那样“从外部”更改。如果要等待其他线程的输入,必须编写以下代码:

extern int flag;
while (flag) { /* loop*/ }
现在,编译器将在每次循环时真正查看标志。这可能比我们在本例中的意图更重要


回答你的问题:如果你知道你在做什么,就用
int l=strlen((char*)数字扔掉volatile(
)在C中没有类似“内置”的解决方法。volatile告诉编译器变量的内容(或者在你的例子中,变量指向的内存)可以在编译器没有注意到的情况下进行更改,并强制编译器直接从数据总线读取数据,而不是使用寄存器中可能存在的副本。 因此,volatile关键字用于避免编译器优化导致的异常行为。(如果你愿意,我可以进一步解释)

在本例中,您有一个声明为volatile的字符缓冲区。如果您的程序在不同的上下文(例如ISR)中更改此缓冲区的内容,则必须实现某种同步机制(例如禁用特定中断等),以避免数据不一致。在获得“锁”(禁用中断)后,您可以将数据逐字节复制到本地(非易失性)缓冲区,并在例程的其余部分使用该缓冲区

如果缓冲区不会在读访问上下文的“外部”更改,我建议省略volatile关键字,因为它没有任何用处


要判断正确的解决方案,需要更多一点关于您的确切用例的信息。

标准库例程不是设计用于
volatile
对象的。最简单的解决方案是在操作易失性存储器之前将其读入普通存储器:

extern volatile int flag;
while (flag) { /* loop*/ }
void ss\u load\u char(易失性字符*位){
字符buf[BUFSIZE];
int i=0;
对于(i=0;i
这里
BUFSIZE
是易失性存储器区域的大小


根据易失性存储器的配置方式,可能需要调用一些例程来复制内容,而不仅仅是使用循环。请注意,
memcpy
不会工作,因为它不是设计用于
volatile
内存。

为什么
sevensegment\u char\u value
首先声明为
volatile
?它是否映射到I/O寄存器,或者它是由另一个线程或中断例程更新的内存?我认为将易失性转换为非易失性是未定义的behavior@PaulR:主程序和ISR都在积极使用此变量。ISR正在读取该值,主程序正在修改该值<代码>加载字符(…)
正在从ISR调用。确定-您如何知道数据在中断时有效?主程序是否在修改数据时禁用中断?(我问的原因是我想确定这里是否真的需要
volatile
。@PaulR:我知道它是有效的,因为它是volatile的,从中读取不会给我带来缓存数据。如果不考虑提高条件,则可以。我只是不想修改这个变量,在ISR中找到旧的值。没有您描述的同步机制。阅读原始帖子中的注释讨论,我必须添加一些内容:听起来好像显示的代码用于接收中断驱动的数据,然后在主循环中进行处理。我强烈建议实现由主循环读取的接收队列,而不是“共享缓冲区”。(我在这里加上这个,因为我还不能写评论。)。很抱歉给您带来不便。您可能想看看伊恩·兰斯·泰勒的博客。泰勒是GCC开发人员之一。他指出您提供的示例中的
volatile
不正确<代码>易失性不用于缓存一致性。
void ss_load_char(volatile char *digits) {
  char buf[BUFSIZE];
  int i = 0;
  for (i = 0; i < BUFSIZE; ++i) {
    buf[i] = digits[i];
  }
  int l=strlen(buf);
  ...
}