Несовместимый тип указателя 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 особенно беспокоит, поскольку, похоже, признает, что два типа идентичны, но все равно жалуется.
2 ответов
консенсус здесь и в других местах, похоже, заключается в том, что GCC делает что-то неожиданное с const и typedef. Я не знаю, что неожиданное обязательно приравнивается к ошибке,но это для разработчиков GCC.
Я решил проблему компиляции, определив макрос для вызова функции, который исправляет несоответствующий тип, который находится внутри библиотеки. Мне вообще не нравится возиться с внутренними библиотеками, но макрос позволяет мне не трогать фактическую библиотеку заголовок и определить его в моем собственном коде, где он может быть прокомментирован в будущем, и тестовое покрытие этого кода должно быть разумным сигналом раннего предупреждения, если базовая библиотека изменяется таким образом, что макрос ломает что-то по дороге.
Это не столько "решено", сколько" обработано", но любое дальнейшее понимание, вероятно, должно исходить от разработчиков GCC.
Если вы набираете cast 'a', чтобы быть ConstSpiceDouble, GCC делает что-то неожиданное с const и typedef, по которому в конечном итоге тип становится "const const double". Это вы можете увидеть в сообщение об ошибке "const ConstSpiceDouble", который приравнивается к "const const double", это не работает.
решение это либо сказать, что " a "является const double или сказать, что" A "является ConstSpiceDouble перед параметром "a" в foo функция
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" pre-pending кажется новой функцией в последних версиях gcc, но в этом я не уверен : (