Well, 我在 GCC 的 Bugzilla 中提了票 https://gcc.gnu.org/bugzilla/show_bug.cgi?id=84166关于这个……约瑟夫·迈尔斯给出了一个简洁的答案:
不,GCC 并不困惑。它说转换是类型安全的uint32_t **
to volatile uint32_t *const *
,但不将其转换为volatile uint32_t *
.
...他还添加了对C 常见问题解答的这一部分 http://c-faq.com/ansi/constmismatch.html.
我必须承认我对此的第一反应是“说什么?”。我快速测试了该建议,更改了代码以使其使用建议的声明(和转换)......
#include <stdlib.h>
#include <stdint.h>
extern void get_buffer_from_HW_driver(volatile uint32_t * const *p);
void getBuffer(volatile uint32_t * const *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 * const *)&p);
}
$ gcc -c -Wall -Wextra -Wcast-qual constqual.c
$
...事实上,不再有警告了。
所以我继续阅读了相关的常见问题解答 - 我想我对正在发生的事情有了更多的了解。通过添加const
修饰符,我们传递的参数是(从右到左阅读,就像我们在这种 C 语法中应该做的那样):
一个指向a的指针constant指向易失性数据的指针(永远不会改变)
这确实很好地映射到这里发生的事情:我得到一个指向易失性数据的指针,这是一个驱动程序提供的缓冲区 - 即一个我确实不被允许改变,因为它来自驱动程序本身分配的预分配缓冲区列表。修改指针get_buffer_from_HW_driver
返回没有任何意义;我不能修改,我只能按原样使用。
我承认我真的很惊讶 C 的类型系统(通过 -Wcast-qual 的真正强大的静态分析检查增强)实际上可以帮助保证这些语义。
非常感谢约瑟夫 - 我将把这个问题留出几周时间,以防其他人想要详细说明。
附:添加一个注释:从现在开始,当有人声称 C 是一种简单语言时,我想我会在这里指出他们。