Предупреждение ISO C forbids converting a string constant to 'char*' появляется при компиляции строки вида char *s = "hello"; с флагами -Wwrite-strings или -pedantic: компилятор GCC либо Clang сообщает, что указатель без const ссылается на строковый литерал, изменять который запрещено стандартом. Это не придирка компилятора, а защита от неопределённого поведения — попытка записи в такую строку обычно завершается падением программы с ошибкой сегментации.

Ошибка особенно часто встречается у тех, кто переходит с C++ на чистый C, собирает старый код современными компиляторами или включает строгие флаги предупреждений в существующем проекте. Ниже разберём, почему возникает это сообщение, чем оно опасно и какие есть корректные способы его устранить — от правильного объявления указателя до копирования строки в изменяемый буфер.

Что означает это предупреждение

Строковый литерал вроде "hello" в C имеет тип массив char, но стандарт запрещает его модифицировать. Компилятор вправе разместить такие литералы в защищённой от записи области памяти (обычно это секция .rodata) и даже объединить одинаковые литералы в один экземпляр. Поэтому указатель на литерал логически должен быть указателем на константные данные.

Когда вы пишете char *s = "hello";, происходит неявное «снятие» константности: указатель позволяет выполнить s[0] = 'H';, что приведёт к неопределённому поведению. В C++ такое присваивание вообще запрещено и является ошибкой компиляции, а в C оно исторически допускалось ради совместимости со старым кодом — но современные компиляторы предупреждают об этом.

Типичный код, вызывающий предупреждение:

char *name = "device"; // предупреждение

char *args[] = {"-l", "-a"}; // предупреждение для каждого элемента

⚠️ Внимание: даже если программа с таким кодом сейчас работает, это не гарантия безопасности. Запись в строковый литерал — неопределённое поведение: на одной платформе будет падение, на другой — тихое повреждение данных или «работающий» код, который сломается после смены компилятора или флагов оптимизации.

Почему компилятор выдаёт это сообщение

Основная причина — включённые строгие проверки. Флаг -Wwrite-strings в GCC и Clang придаёт строковым литералам тип const char[], после чего любое присваивание литерала указателю char* диагностируется. Флаги -pedantic и -Wpedantic также усиливают проверки соответствия стандарту.

Вторая частая причина — сборка старого C-кода компилятором C++ или с опцией -x c++. В C++ присваивание строкового литерала типу char* запрещено начиная со стандарта C++11 (устаревшим оно было объявлено ещё раньше), поэтому там вы увидите не предупреждение, а ошибку.

  • 🔧 Флаги сборки: проверьте, не добавлены ли -Wwrite-strings, -pedantic или -Wall -Wextra в CFLAGS проекта.
  • 📦 Устаревший код: библиотеки, написанные до широкого распространения const-корректности, массово используют char* для литералов.
  • 🔀 Смешение C и C++: заголовки или исходники, собираемые не тем режимом компилятора.
  • ⚙️ API без const: сторонние функции, принимающие char*, хотя не изменяют строку.
📊 Как вы столкнулись с этим предупреждением?