C语言 结构中的Volatile导致宏中出现警告

q5iwbnjs  于 2023-02-03  发布在  其他
关注(0)|答案(2)|浏览(478)

我使用以下类型:

/* double_buffer.h */

typedef struct
{
    uint8_t * active_buffer_p;       //< Address of active buffer
    uint8_t current_writing_index;   //< Current writing index in active buffer
    uint8_t buffer_1[BUFFER_SIZE];   //< First buffer
    uint8_t buffer_2[BUFFER_SIZE];   //< Second buffer
} double_buffer_t;

#define DoubleBuffer_init(buffers) do {                 \
        (buffers).active_buffer_p = (buffers).buffer_1; \
        (buffers).current_writing_index = 0;            \
        } while(0)

在我的代码中,我使用volatile键声明了一个双缓冲区数组(因为缓冲区可以在中断和函数中异步更新/读取):

static volatile double_buffer_t m_double_buffers[NB_DOUBLE_BUFFERS];

然后,我分别初始化这些缓冲区:

DoubleBuffer_init(m_double_buffers[id]);

当我编译软件(gcc)时,我得到了以下警告:

error: assignment discards 'volatile' qualifier from pointer target type [-Werror=discarded-qualifiers]
   28 |         (buffers).active_buffer_p = (buffers).buffer_1; \

为什么我有这个警告的原因是我很不清楚,我不知道如何修复它。
任何帮助将不胜感激(我可以更新的问题,如果有什么不清楚)。

jm81lzqq

jm81lzqq1#

您收到此警告是因为您有一个volatile对象,并且您创建了一个指向它的非volatile指针。
这是很糟糕的,因为编译器可以访问volatile对象而不知道它是volatile对象。例如,它可以将两次读取转换为一次读取,它可以改变顺序等。
一种解决方法是将active_buffer_p定义为uint8_t volatile * active_buffer_p

vvppvyoh

vvppvyoh2#

当您将一个struct变量声明为volatile时,每个成员对象都会获得volatile限定,就像您这样编写结构一样:

typedef struct
{
    uint8_t* volatile active_buffer_p; 
    volatile uint8_t current_writing_index;
    volatile uint8_t buffer_1[10];
    volatile uint8_t buffer_2[10];
} double_buffer_t;

也就是说,在指针成员的情况下,指针本身转向volatiletype* volatile =指针的地址可能在任何时候改变,而不是它应该指向的地方。volatile type* =所指向的数据可能在任何时候改变。
所以当你赋值的时候,buffer_1“数组衰减”为volatile uint8_t*,然后你试图把它赋值给一个被限定为uint8_t* volatile的指针,指针类型是不兼容的,因为它们有不同的限定符。
解决方法是声明指针成员volatile uint8_t* active_buffer_p;,然后如果结构体变量声明为volatile,它就变成volatile uint8_t* volatile(指针和它所指向的对象可能随时改变),我们总是可以将一个“非限定”指针赋给一个有更多限定符的指针,但不能反过来。
const的工作方式完全相同。
顺便说一句,init宏很难看,除了混淆之外没有任何用途。考虑放弃它,以支持可读代码:

static volatile double_buffer_t m_double_buffers[NB_DOUBLE_BUFFERS] =
{
  [0] = { .active_buffer_p = m_double_buffers[0].buffer_1, 
          .current_writing_index = 0 },
  [1] = { .active_buffer_p = m_double_buffers[1].buffer_1, 
          .current_writing_index = 0 },
  [2] = { .active_buffer_p = m_double_buffers[2].buffer_1, 
          .current_writing_index = 0 },
};

或100%等效:

static volatile double_buffer_t m_double_buffers[NB_DOUBLE_BUFFERS] =
{
  [0] = { .active_buffer_p = m_double_buffers[0].buffer_1, },
  [1] = { .active_buffer_p = m_double_buffers[1].buffer_1, },
  [2] = { .active_buffer_p = m_double_buffers[2].buffer_1, },
};

相关问题