如何让 volatile 函数参数起作用?
How do I get a volatile function argument working?
我对 C++ 完全没有经验,我一直使用 C。在我最近的业余爱好项目中,我需要将 C++ 库与我的 C 代码混合,从而迫使我拥有 C++ main.cpp.
我现在正在干预我的 C 代码以编译为 C++。除了一个我根本无法解决的问题外,这甚至工作得很好。
这是一个中断服务,每秒递增我的 unix 时间变量,然后还转换成拆分时间格式。由于这发生在中断中,我将变量设置为易失性。
volatile time_t UNIX_TIME = 0;
volatile struct tm TIME_CUR_LOCALTIME;
if (htim == &htim2){
UNIX_TIME++;
TIME_CUR_LOCALTIME = *localtime(&UNIX_TIME);
}
来自图书馆 time.h:
struct tm *localtime (const time_t *_timer);
使用 gcc
这编译完美。
g++
是另一回事。它给了我错误:
error: passing 'volatile tm' as 'this' argument discards qualifiers [-fpermissive]
我尝试了多次强制转换和其他操作,它开始自行工作的唯一方法是当我删除 both volatile 限定符时。但我不想那样。
实现此功能的正确方法是什么?我没主意了。
首先将时间复制到非易失性实例中:
time_t t = UNIX_TIME;
tm local = *localtime(&t);
TIME_CUR_LOCALTIME.tm_sec = local.tm_sec;
TIME_CUR_LOCALTIME.tm_min = local.tm_min;
TIME_CUR_LOCALTIME.tm_hour = local.tm_hour;
TIME_CUR_LOCALTIME.tm_mday = local.tm_mday;
TIME_CUR_LOCALTIME.tm_mon = local.tm_mon;
TIME_CUR_LOCALTIME.tm_year = local.tm_year;
TIME_CUR_LOCALTIME.tm_wday = local.tm_wday;
TIME_CUR_LOCALTIME.tm_yday = local.tm_yday;
TIME_CUR_LOCALTIME.tm_isdst = local.tm_isdst;
C 标准和 C++ 标准都没有尝试区分将以编译器没有理由期望的方式修改的对象,以及将仅以编译器理解的方式编写但也可能是以它没有理由期望的方式读取,而那些虽然声明为 volatile
,但实际上永远不会以编译器不期望的方式访问的方式(后一种情况可能出现在有时会被使用的库中在通过外部方式访问事物的系统中,有时在不通过外部方式访问事物的系统中使用)。所有可能以编译器不期望的方式访问的非原子对象都必须被限定 volatile
,并且因为——从标准的角度来看——所有被限定的对象 volatile
可能是以任意外部方式读取或写入,任何不使用 volatile
限定符访问此类对象都会调用未定义行为,而不考虑是否实际发生任何外部访问。该标准的作者可能认识到,由于希望销售编译器的人会明智地处理此类情况,而不管他们是否被要求这样做,因此该标准没有必要解决此类情况。然而,并非所有编译器编写者都受该原则约束。
实现此处问题行为的最佳方法可能是将 UNIX_TIME
复制到几个普通对象,确保它们匹配,如果不匹配则重复读取尝试,然后传递地址对于任何需要保存时间的对象的地址的函数。正如其他地方所指出的,应该避免像 localtime
这样使用静态缓冲区的函数,使用像 localtime_r
这样的函数,但是如果想要关闭编译器,重要的是在使用之前将对象复制到其他地方。
我对 C++ 完全没有经验,我一直使用 C。在我最近的业余爱好项目中,我需要将 C++ 库与我的 C 代码混合,从而迫使我拥有 C++ main.cpp.
我现在正在干预我的 C 代码以编译为 C++。除了一个我根本无法解决的问题外,这甚至工作得很好。
这是一个中断服务,每秒递增我的 unix 时间变量,然后还转换成拆分时间格式。由于这发生在中断中,我将变量设置为易失性。
volatile time_t UNIX_TIME = 0;
volatile struct tm TIME_CUR_LOCALTIME;
if (htim == &htim2){
UNIX_TIME++;
TIME_CUR_LOCALTIME = *localtime(&UNIX_TIME);
}
来自图书馆 time.h:
struct tm *localtime (const time_t *_timer);
使用 gcc
这编译完美。
g++
是另一回事。它给了我错误:
error: passing 'volatile tm' as 'this' argument discards qualifiers [-fpermissive]
我尝试了多次强制转换和其他操作,它开始自行工作的唯一方法是当我删除 both volatile 限定符时。但我不想那样。
实现此功能的正确方法是什么?我没主意了。
首先将时间复制到非易失性实例中:
time_t t = UNIX_TIME;
tm local = *localtime(&t);
TIME_CUR_LOCALTIME.tm_sec = local.tm_sec;
TIME_CUR_LOCALTIME.tm_min = local.tm_min;
TIME_CUR_LOCALTIME.tm_hour = local.tm_hour;
TIME_CUR_LOCALTIME.tm_mday = local.tm_mday;
TIME_CUR_LOCALTIME.tm_mon = local.tm_mon;
TIME_CUR_LOCALTIME.tm_year = local.tm_year;
TIME_CUR_LOCALTIME.tm_wday = local.tm_wday;
TIME_CUR_LOCALTIME.tm_yday = local.tm_yday;
TIME_CUR_LOCALTIME.tm_isdst = local.tm_isdst;
C 标准和 C++ 标准都没有尝试区分将以编译器没有理由期望的方式修改的对象,以及将仅以编译器理解的方式编写但也可能是以它没有理由期望的方式读取,而那些虽然声明为 volatile
,但实际上永远不会以编译器不期望的方式访问的方式(后一种情况可能出现在有时会被使用的库中在通过外部方式访问事物的系统中,有时在不通过外部方式访问事物的系统中使用)。所有可能以编译器不期望的方式访问的非原子对象都必须被限定 volatile
,并且因为——从标准的角度来看——所有被限定的对象 volatile
可能是以任意外部方式读取或写入,任何不使用 volatile
限定符访问此类对象都会调用未定义行为,而不考虑是否实际发生任何外部访问。该标准的作者可能认识到,由于希望销售编译器的人会明智地处理此类情况,而不管他们是否被要求这样做,因此该标准没有必要解决此类情况。然而,并非所有编译器编写者都受该原则约束。
实现此处问题行为的最佳方法可能是将 UNIX_TIME
复制到几个普通对象,确保它们匹配,如果不匹配则重复读取尝试,然后传递地址对于任何需要保存时间的对象的地址的函数。正如其他地方所指出的,应该避免像 localtime
这样使用静态缓冲区的函数,使用像 localtime_r
这样的函数,但是如果想要关闭编译器,重要的是在使用之前将对象复制到其他地方。