在没有 typedef 的情况下使用时显示编译错误的函数的 volatile 指针;需要帮助 "void (* volatile userFunc)(void)"
volatile pointer to function showing compile error when using without typedef; need help w/ "void (* volatile userFunc)(void)"
我正在使用 C++ classes 编写 Arduino 库。在 class 中,我有一个私有成员变量,它是一个指向函数的指针。
问题是我需要指针是可变的,因为指向函数的指针将在 外部 ISR 中设置,并且可以在程序执行期间更改,但是函数将在 一个 ISR 中被调用。因此,我想我需要一个指向非易失性函数的易失性指针,对吗?
无论如何,我正在做的是创建一种允许自定义用户函数的机制,该函数将由我的库定期调用。
这是基础知识:
这只是展示了您可以看到的重要部分。
.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 中执行此操作,它会编译:
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?
附加问题:
上面第一个背景link说:
"Volatile pointers to non-volatile data are very rare (I think I've used them once), but I'd better go ahead and give you the syntax:"
int * volatile p;
那么,你会在什么时候使用上述技巧?就我而言?
问题
语句 volatile void (*userOverflowFunction)(void);
表示您有一个指向函数 return 类型 volatile void
的指针。
虽然 volatile void
比较概念化(更容易理解 volatile int
是什么),但它仍然是有效的 return类型,并且它与 doSomething()
的 return 类型不匹配。
解决方法
你说你希望指针是可变的。
用 C++ 翻译它得到:void (* volatile userOverflowFunction)(void);
在这里你有了第一个发现。
您描述的第二个发现对应于定义函数指针类型,然后说它是该类型的易失性指针。两者是等价的。
编辑:补充说明
您使用的方法完全合乎逻辑:您的函数不是易失性的(正如 Kerrek 已经在评论中指出的那样),但是您的中断处理程序需要获取指针的值,该指针可能已在易失性中更改方式。
您可能也有兴趣阅读有关 std::signal
的内容。由于您的函数指针不是 volatile std::sig_atomic_t
,您应该考虑使用第二种方法将其设为原子:std::atomic<voidFuncPtr> userOverflowFunction;
我正在使用 C++ classes 编写 Arduino 库。在 class 中,我有一个私有成员变量,它是一个指向函数的指针。
问题是我需要指针是可变的,因为指向函数的指针将在 外部 ISR 中设置,并且可以在程序执行期间更改,但是函数将在 一个 ISR 中被调用。因此,我想我需要一个指向非易失性函数的易失性指针,对吗?
无论如何,我正在做的是创建一种允许自定义用户函数的机制,该函数将由我的库定期调用。
这是基础知识:
这只是展示了您可以看到的重要部分。
.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 中执行此操作,它会编译:
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?
附加问题:
上面第一个背景link说:
"Volatile pointers to non-volatile data are very rare (I think I've used them once), but I'd better go ahead and give you the syntax:"
int * volatile p;
那么,你会在什么时候使用上述技巧?就我而言?
问题
语句 volatile void (*userOverflowFunction)(void);
表示您有一个指向函数 return 类型 volatile void
的指针。
虽然 volatile void
比较概念化(更容易理解 volatile int
是什么),但它仍然是有效的 return类型,并且它与 doSomething()
的 return 类型不匹配。
解决方法
你说你希望指针是可变的。
用 C++ 翻译它得到:void (* volatile userOverflowFunction)(void);
在这里你有了第一个发现。
您描述的第二个发现对应于定义函数指针类型,然后说它是该类型的易失性指针。两者是等价的。
编辑:补充说明
您使用的方法完全合乎逻辑:您的函数不是易失性的(正如 Kerrek 已经在评论中指出的那样),但是您的中断处理程序需要获取指针的值,该指针可能已在易失性中更改方式。
您可能也有兴趣阅读有关 std::signal
的内容。由于您的函数指针不是 volatile std::sig_atomic_t
,您应该考虑使用第二种方法将其设为原子:std::atomic<voidFuncPtr> userOverflowFunction;