不稳定结构的不透明指针

Tob*_*oby 4 c struct volatile

我有一个简单的FIFO环缓冲队列,我在我的嵌入式C程序中使用(使用TI C28x C/C++编译器,它非常类似于没有扩展的C89的GCC).数据被中断队列推送和弹出,因此队列需要是易失性的.

我已经实现了队列代码而不使用volatile,因此队列用户可以选择队列是否是易失性的(我希望在具有不同用途的几个项目中使用它),通过将句柄声明为volatile在使用中队列对象,而不是在实现中将队列对象本身定义为volatile.

即在que.c中:

struct QUE_Obj { /* Object & members are not defined as volatile. */
    void * data;
    uint16_t capacity;
    uint16_t head;
    uint16_t tail;
    uint16_t size;
    bool full;
    bool empty;
}

/* Implementation uses all non-volatile types. */
QUE_Handle QUE_init(void * data, uint_least8_t size, uint16_t capacity) { 
    /* ... */ 
    QUE_Handle q = (QUE_Handle)malloc(sizeof(struct QUE_Obj));
    /* ... */
    return q;
}

/* ... */
Run Code Online (Sandbox Code Playgroud)

在queue.h中:

typedef QUE_Obj * QUE_Handle;
QUE_Handle QUE_init(void * data, uint_least8_t size, uint16_t capacity)
Run Code Online (Sandbox Code Playgroud)

在main.c中:

/* Data buffer and queue handle declared to be for volatile data. */
static volatile uint16_t buffer[BUFFER_LENGTH] = {0};
volatile QUE_Handle que = QUE_init((void *)buffer); /* Buffer passed without volatile. */
Run Code Online (Sandbox Code Playgroud)

那么我的问题是,在C语言的最后一行,当我转换缓冲区时void *,这是否会消除波动率的任何有用性?

我是否应该定义QUE_Obj始终为volatile 的成员,并将实现中使用的类型调整为volatile,而不管队列的使用情况如何?

问另一个方式,push()并且pop()功能从中断服务子程序调用,但其实施并不"知道"的波动,他们将被优化掉?

mzi*_*ard 5

您不应该通过非易失性指针访问volatile数据.考虑以下简单示例:

volatile int volatileVar;
int* nonVolatilePtr = &volatileVar;
Run Code Online (Sandbox Code Playgroud)

每当您volatileVar通过nonVolatilePtr编译器访问代码时,都不知道您访问的数据是易失性的,并且可能会优化对它的访问(这显然是一种不受欢迎的行为).我发现很少使用非易失性指针来处理易失性数据.

如果您希望您的队列可能被中断服务程序(或类似程序)访问,我会使整个数据结构变得不稳定.