我正在使用 C++ 类编写 Arduino 库。在类内部,我有一个私有(private)成员变量,它是一个指向函数的指针。
问题是我需要指针是可变的,因为指向函数的指针将被设置为外部一个ISR,并且可以在程序执行期间更改,但是函数将被调用在 ISR 中。因此,我认为我需要一个指向非 volatile 函数的 volatile 指针,对吗?
无论如何,我正在做的是创建一种允许自定义用户函数的机制,该函数将由我的库定期调用。
基础知识:
这只是展示了您可以看到的基本部分。
.h文件
class myLib
{
public:
void attachOverflowInterrupt(void (*myFunc)());
private:
volatile void (*userOverflowFunction)(void);
}
.cpp文件
void myLib::attachOverflowInterrupt(void (*myFunc)())
{
//ensure atomic access
uint8_t SREGbak = SREG; //back up interrupt state
noInterrupts(); //interrupts off
userOverflowFunction = myFunc; //attach function //<--the part that matters to my problem here
SREG = SREGbak; //restore interrupt state
}
//inside the interrupt, their function is called essentially like this:
this->userOverflowFunction();
Arduino .ino 文件(只显示必要部分)
void doSomething()
{
}
myLib1.attachOverflowInterrupt(doSomething);
此代码无法编译。我收到此错误:
error: invalid conversion from 'void (*)()' to 'volatile void (*)()' [-fpermissive] userOverflowFunction = myFunc; //attach function
但是,如果我在类里面这样做,它会编译:
class myLib
{
public:
void attachOverflowInterrupt(void (*myFunc)());
//volatile void (*userOverflowFunction)(void); //compile error
void (* volatile userOverflowFunction)(void); //<---compiles
}
或者,如果我改为这样做,它会编译:
typedef void (*voidFuncPtr)(void);
class myLib
{
public:
void attachOverflowInterrupt(void (*myFunc)());
//volatile void (*userOverflowFunction)(void); //compile error
//void (* volatile userOverflowFunction)(void); //compiles
volatile voidFuncPtr userOverflowFunction; //<---compiles
}
那么,导致第一个失败但后两个编译的这三件事之间有什么区别?
volatile void (*userOverflowFunction)(void); //compile error
void (* volatile userOverflowFunction)(void); //compiles
volatile voidFuncPtr userOverflowFunction; //compiles
我做过的背景阅读:
- http://www.barrgroup.com/Embedded-Systems/How-To/C-Volatile-Keyword
- Why is a point-to-volatile pointer, like "volatile int * p", useful?
附加问题:
上面的第一个背景链接指出:
“指向非 volatile 数据的 volatile 指针非常少见(我想我已经用过一次),但我最好继续为您提供语法:”
int * volatile p;
那么,您什么时候会使用上述技术?就我而言?
最佳答案
问题
声明volatile void (*userOverflowFunction)(void);
说你有一个指向返回类型 volatile void
的函数的指针.
虽然 volatile void
相当概念化(更容易理解 volatile int
是什么),它仍然是一个有效的返回类型,并且它与 doSomething()
的返回类型不匹配.
解决方案
你说你希望指针是可变的。
用 C++ 翻译它给出:void (* volatile userOverflowFunction)(void);
这是你的第一个发现。
您描述的第二个发现对应于定义函数指针类型,然后说它是该类型的 volatile 指针。两者是等价的。
编辑:补充说明
您使用的方法完全合乎逻辑:您的函数不是易变的(正如 Kerrek 已经在评论中指出的那样),但是您的中断处理程序需要获取可能以易变方式更改的指针的值。
您可能也有兴趣阅读有关 std::signal
的内容.因为你的函数指针不是 volatile std::sig_atomic_t
,您应该考虑使用第二种方法使其成为原子:std::atomic<voidFuncPtr> userOverflowFunction;
关于c++ - 在没有 typedef 的情况下使用时显示编译错误的函数的 volatile 指针;需要帮助 w/"void (* volatile userFunc)(void)",我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31898819/