我有一些代码在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的说明特别令人不安,因为它似乎承认这两种类型是相同的,但无论如何都会抱怨。
答案 0 :(得分:2)
此处和其他地方的共识似乎是GCC正在使用const和typedef做出意想不到的事情。我不知道意外必然等同于一个错误,但GCC开发人员确定这个错误。
我通过为函数调用定义一个宏来解决我的编译问题,该宏修复了库中不匹配的类型转换。我一般不喜欢修改库内部,但是宏允许我不触及实际的库头并在我自己的代码中定义它,以便将来可以对它进行注释,如果代码的测试覆盖率应该是合理的预警信号,如果底层库的变化使得宏破坏了一些东西。
这不是很多"解决了#34; as"解决了问题,但任何进一步的见解都可能来自GCC开发者。
答案 1 :(得分:1)
如果输入强制转换'a'为ConstSpiceDouble,GCC会使用const和typedef执行一些意外操作,最终类型变为'const const double'。您可以在错误消息“const ConstSpiceDouble”中看到,这相当于'const const double',这不起作用。
解决方案要么说'a'是const double,要么在将'a'参数设置为foo函数之前说'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中的一个新功能,但是,我不确定:(