在没有 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

我完成的背景阅读:

  1. http://www.barrgroup.com/Embedded-Systems/How-To/C-Volatile-Keyword
  2. 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;