【发布时间】:2018-02-01 10:41:36
【问题描述】:
在下面的代码中...
#include <stdlib.h>
#include <stdint.h>
extern void get_buffer_from_HW_driver(volatile uint32_t **p);
void getBuffer(volatile uint32_t **pp)
{
// Write an address into pp, that is obtained from a driver
// The underlying HW will be DMA-ing into this address,
// so the data pointed-to by the pointer returned by this
// call are volatile.
get_buffer_from_HW_driver(pp);
}
void work()
{
uint32_t *p = NULL;
getBuffer((volatile uint32_t **)&p);
}
...编译器正确地检测到对p 在work 中指向的数据的任何潜在访问都是危险访问。照原样,代码指示编译器可以安全地发出代码以优化对 *p 的重复读取访问 - 这确实是错误的。
但奇怪的是,编译这段代码时发出的警告...
$ gcc -c -Wall -Wextra -Wcast-qual constqual.c
...不会抱怨volatile 的丢失——而是建议使用const:
constqual.c: In function ‘work’:
constqual.c:20:15: warning: to be safe all intermediate pointers in cast from
‘uint32_t ** {aka unsigned int **}’ to ‘volatile uint32_t **
{aka volatile unsigned int **}’ must be ‘const’ qualified
[-Wcast-qual]
getBuffer((volatile uint32_t **)&p);
^
我看不出const 在这里有什么意义。
附:请注意,按预期在uint32_t *p 前面添加volatile 可以解决此问题。我的问题是为什么 GCC 推荐 const 而不是 volatile。
【问题讨论】:
-
我怀疑您在编译器消息中发现了一个错误。编译器很可能根据相同的规则处理所有类型限定符,但与常用的“const-correctness”相比,“volatile-correctness”是一种罕见的野兽。所以也许在编码时,他们将
const这个词“硬编码”到消息中,却没有意识到volatile、restrict和_Atomic也是如此。 -
请注意,
clang确实发出了相同的警告(措辞略有不同,但指的是const)。有没有办法找到此类警告消息的来源? -
@Lundin 确实,看起来很有可能。我打开了a ticket in GCC's Bugzilla - 让我们看看开发人员怎么说。
-
@Lundin GCC dev 回复 - 在下面总结了我对他们回复的理解。
-
@Lundin 常量正确性要求
Foo ***安全地转换为Foo const * const * const *。也许令人惊讶的是,volatile-correctness 不意味着Foo ***安全地转换为Foo volatile * volatile * volatile *--- 它转换为Foo volatile * const * const *。这就是消息的意思。