GCC使用typedef的指针类型不兼容

我有一些代码在GCC 4.8.4下编译得很好。 我最近升级了我的系统,现在有GCC 5.2.1,我收到有关不兼容指针类型的警告。 我已经将问题提取到一个重现错误的小例子:

typedef const double ConstSpiceDouble; void foo(const double (*)[3]); int main(int argc, char **argv) { double a[3][3] = {{1,2,3},{1,2,3},{1,2,3}}; foo((ConstSpiceDouble (*)[3])a); return 0; } 

在实际代码中,typedef,函数定义和类型转换都在我控制之外的库中,否则我只需修复转换和匹配的函数。 这是我从编译器得到的消息:

 $ gcc -Werror -c test.c test.c: In function 'main': test.c:9:7: error: passing argument 1 of 'foo' from incompatible pointer type [-Werror=incompatible-pointer-types] foo((ConstSpiceDouble (*)[3])a); ^ test.c:4:6: note: expected 'const double (*)[3]' but argument is of type 'const ConstSpiceDouble (*)[3] {aka const double (*)[3]}' void foo(const double (*)[3]); ^ cc1: all warnings being treated as errors 

来自gcc的说明特别令人不安,因为它似乎承认这两种类型是相同的,但无论如何它都会抱怨。

这里和其他地方的共识似乎是GCC正在使用const和typedef做出意想不到的事情。 我不知道意外必然等同于一个错误,但这是由GCC开发人员确定的。

我通过为函数调用定义一个宏来解决我的编译问题,该宏修复了库中不匹配的类型转换。 我一般不喜欢修改库内部,但是宏允许我不触及实际的库头并在我自己的代码中定义它,以便将来可以对它进行注释,并且测试覆盖该代码应该是一个合理的预警信号,如果底层库以这样一种方式发生变化,即宏破坏了一些东西。

这并没有像“解决”那样“解决”,但任何进一步的见解都可能来自GCC开发者。

如果你输入’a’作为ConstSpiceDouble,GCC会用const和typedef做一些意想不到的事情,最终这个类型变成’const const double’。 您可以在错误消息 “const ConstSpiceDouble”中看到,这相当于’const const double’,这不起作用。

解决方法是在将参数’a’与foo函数进行参数之前说’a’是const double或者说’a’是ConstSpiceDouble

 typedef const double ConstSpiceDouble; void foo(const double (*)[3]); int main(int argc, char **argv) { const double a[3][3] = {{1,2,3},{1,2,3},{1,2,3}}; // or ConstSpiceDouble a[3][3] = {{1,2,3},{1,2,3},{1,2,3}}; foo(a); return 0; } 

‘const’预先挂起似乎是最新版本的gcc中的一个新function,但是,我不确定:(