Как работает этот метод, вызываемый с макросом КЛАССА?

#c

Вопрос:

Недавно я получил просьбу от знакомого помочь в создании решения на C после того, как их разработчик, к сожалению, скончался. Я относительно новичок в C и не совсем понимаю, что делают следующие строки.

Этот код взят из настроенной версии dcraw.cpp библиотека Дэйва Коффина.

МАКРОС определяется как

 #define CLASS
 

Вызываемый метод выглядит следующим образом

  void CLASS merror (void *ptr, char *where)
{
     if ( ptr ) return;
     //fprintf (stderr,_("%s: Out of memory in %sn"), ifname, where);
     sprintf (PSstring(),"%s: Out of memory in %sn", ifname, where);
     PSputDiag ();
     longjmp (failure, 1);
}
 

И вызов метода выглядит так

 merror (fimg, "wavelet_denoise()");
 

При попытке скомпилировать код я получаю около 1800 ошибок, 258 из которых похожи на следующие.

C2664 ‘void merror(void *,char *)’: не удается преобразовать аргумент 2 из ‘const char [15]’ в ‘char *’ Фотосессия 5 C:UserssourceprojectnameMVDcraw.cpp 991

Я довольно долго искал, чтобы выяснить, что происходит, но так как я даже не знаю, что делает вызов метода, я не смог найти ничего, что имеет отношение к делу.

Любая помощь будет очень признательна.

Комментарии:

1. CLASS это не имеет значения. "wavelet_denoise()" является постоянным строковым литералом и merror ожидает неконстантности. Измените char *where на char const *where . Также longjmp в программе на C есть большой красный флаг «…Никакие деструкторы для автоматических объектов не называются….» en.cppreference.com/w/cpp/utility/program/longjmp.

2. Измените прототип на void CLASS merror(void *ptr, const char *where) . Вы можете полностью опустить эту CLASS часть, если только она не нужна какому-либо другому инструменту или утилите. (Некоторые компиляторы разрешали передавать символьные строки в char * качестве расширения.)

Ответ №1:

Макрос

#определить КЛАСС

не имеет никакого отношения к вашей ошибке. После расширения макроса функция:

  void merror (void *ptr, char *where)
{
     if ( ptr ) return;
     //fprintf (stderr,_("%s: Out of memory in %sn"), ifname, where);
     sprintf (PSstring(),"%s: Out of memory in %sn", ifname, where);
     PSputDiag ();
     longjmp (failure, 1);
}
 

То есть макрос заменяется ничем.

Код, по-видимому, был написан до C 11. От cppreference

до C 11:

Строковые литералы преобразуются и присваиваются неконстантным символам* или wchar_t*, чтобы быть совместимыми с C, где строковые литералы имеют типы char[N] и wchar_t[N]. Такое неявное преобразование не рекомендуется.

начиная с C 11:

Строковые литералы не преобразуются и не могут быть назначены для неконстантной диаграммы*. Если требуется такое преобразование, необходимо использовать явное приведение (например, const_cast).

Преобразование строковых литералов в char* никогда не было в порядке, но только с C 11 это ошибка. Если вы используете C 17, вы можете использовать std::string::data() :

  std::string where{"wavelet_denoise()"};
 merror (fimg, where.data());
 

На самом деле лучше было бы изменить метод, как предложено в комментарии Ричарда Криттена, чтобы взять const char* where А.