Каков правильный способ приведения const char* к char* без изменения API и без предупреждения

В моем простом проекте C99 у меня есть внешняя библиотека C, которая определяет интерфейс (через интерфейсы GObject).), которые мне нужно реализовать:

void interface_function (const char *address, [...]);

Теперь в рамках реализации (которую мне нужно написать) мне нужно вызвать некоторые другие функции из другой библиотеки (поэтому я не могу их изменить), которым мне нужно передать *address, но в сигнатуре их метода опущено ключевое слово const:

void some_api_function (char *address, [...]);

Теперь, если я просто передам *address вниз к some_api_function, я получу предупреждение компилятора:

warning: passing argument 1 of ‘some_api_function’ discards ‘const’ qualifier from pointer target type [enabled by default]

Я попытался явно указать char * в вызове функции следующим образом:

`some_api_function ((char*) address, [...]) { ... }

но потом я просто получаю еще одно предупреждение:

warning: cast discards ‘__attribute__((const))’ qualifier from pointer target type [-Wcast-qual]

Проблема в том, что это более крупный проект C, над которым работает много людей, и политика заключается в том, что -Werror включен, и код, выдающий предупреждения при компиляции, не принимается в основной исходный код.

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

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

Итак, каков элегантный или «правильный» способ сделать это?


person Dynalon    schedule 02.10.2013    source источник
comment
Ничего себе, я не знал, что вы можете получить такие предупреждения о явных приведениях... Полезно знать, что в C++ это может привести к явному использованию const_cast вместо приведения в стиле C...   -  person Medinoc    schedule 02.10.2013


Ответы (3)


Для абсолютной безопасности я бы глубоко скопировал строку и профилировал влияние на производительность. Автор функции не гарантирует, что он не изменит строку. Если параметр отмечен const char*, подразумевается, что строка не будет изменена функцией.

Есть и другие варианты; кастинг через (void*) или хитрый трюк с объединением (см. ответ Гунг Фу), но ни один из них не гарантирует стабильность программы.

person Bathsheba    schedule 02.10.2013
comment
Просмотр в коде внешней библиотеки показывает, что разработчики просто не хотели помечать параметр как константный. Тем не менее, используя подход копирования. На производительность не повлияет, просто не понравилось. Но если это рекомендуемый способ сделать, я пойду на это. - person Dynalon; 02.10.2013
comment
Попросите разработчиков изменить заголовок библиотеки - person Demi; 18.11.2013

Можно использовать союз.

union charunion {
   char *chr;
   const char* cchr;
} chrptrs;

chrptrs.cchr; // const char *
chrptrs.chr;  // char *
person Gung Foo    schedule 02.10.2013

Предупреждения существуют не просто так. Как говорит Bathseheeba, объявление не гарантирует, что функция не изменит значение, поэтому, если вы знаете, что делаете, -т.е. вы знаете, что функция не будет пытаться изменить значение, указанное «адресом», вы можете удалить предупреждение, выполнив следующие действия:

void interface_function (const char *address, [...])
{
    char *chrptr=(char *)address;
    [...]
    some_api_function (chrptr, [...]);
    [...]
 }

РЕДАКТИРОВАТЬ: я отвечал до того, как вы прокомментировали, что согласны с предложением Вирсавии. Хороший выбор.

person guilleamodeo    schedule 02.10.2013
comment
Использование вашего подхода приведет к предупреждению warning: cast discards ‘__attribute__((const))’ qualifier from pointer target type [-Wcast-qual]. Однако это не включено по умолчанию в gcc, но включено из-за политики проектов с -Wcast-qual - person Dynalon; 02.10.2013
comment
Что ж, я не ожидал, что вы захотите удалить предупреждение, которое вы попросили выдать компилятор... Тогда ваш единственный подход - это подход Гунг Фу. - person guilleamodeo; 02.10.2013
comment
Таким образом, это звучит так, как будто я занимаюсь ерундой. Но, как сказано в моем вопросе, вы - это не я один, а большая группа разработчиков, и я лишь второстепенный участник, поэтому я не могу решить удалить предупреждения из системы сборки, поскольку это политические решения. - person Dynalon; 02.10.2013
comment
Пожалуйста, не поймите меня неправильно. Я не имел в виду, что ты занимаешься ерундой, просто это было немного неожиданно. :-) - person guilleamodeo; 02.10.2013