Неплохо ли объявлять строку C-стиля без const? Если да, то почему?

Выполнение этого в С++

char* cool = "cool";

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

устаревшее преобразование из строковой константы в char *.

Я бы никогда не намеренно использовал строку стиля C над std::string, но на всякий случай мне задали этот вопрос:

Плохая практика объявлять строку C-стиля без модификатора const? Если да, то почему?

Ответ 1

Да, это объявление является плохой практикой, поскольку оно позволяет много способов случайного провоцирования поведения Undefined путем записи в строковый литерал, включая:

cool[0] = 'k';
strcpy(cool, "oops");

С другой стороны, это прекрасно, поскольку он выделяет неконстантный массив символов:

char cool[] = "cool";

Ответ 2

Да, в С++ вы всегда должны ссылаться на строковые литералы с переменными типа const char * или const char [N]. Это также наилучшая практика при написании нового кода C.

Строковые литералы хранятся в постоянной памяти, когда это возможно; их тип надлежащим образом const -qualified. C, но не С++, включает бонусы обратной совместимости, где компилятор дает им тип char [N], даже если они хранятся в постоянной памяти. Это связано с тем, что строковые литералы старше, чем const. const был изобретен в преддверии того, что теперь называется "C89" - более ранняя форма "K & R" языка не имела этого.

Некоторые компиляторы C включают дополнительный режим, в котором бородавка с обратной совместимостью отключена, а char *foo = "..."; предоставит вам ту же или аналогичную диагностику, что и на С++. GCC запускает этот режим -Wwrite-strings. Я настоятельно рекомендую его для нового кода; тем не менее, включение его для старого кода может потребовать огромного количества инструментов для очень мало пользы.

Ответ 3

Это плохо. Это очень плохо. К тому, что это невозможно сделать в С++ 11.

Модификация памяти строкового литерала - это поведение undefined.

Ответ 4

Во-первых, char* cool = "cool"; не является стандартным С++. Строковый литерал имеет тип const char[n]. Таким образом, вышеприведенная строка кода нарушает const-correctness и не должна компилироваться. Некоторые компиляторы, такие как GCC, разрешают это, но вызывают предупреждение, так как это ограничение от C. MSVC выдает ошибку, поскольку это ошибка.

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

Ответ 5

Это плохо, потому что строковые константы могут содержаться только один раз на двоичный (ключевое слово: stringtable, .strtab). Например. в

char *cool = "cool";
char *nothot = "cool";

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

strcpy(nothot, "warm");

ваш cool станет "теплым".

Короче говоря, это поведение undefined.

Ответ 6

Это строковый литерал, поэтому он должен быть постоянным, так как память может находиться в разделе только для чтения. Если у вас char cool[] = "cool";, то это не проблема, память принадлежит вам.

Ответ 7

char * cool = "cool"

"cool" будет храниться в блоке только для чтения (обычно в сегменте данных), который разделяется между функциями. Если вы попытаетесь изменить строку "cool" на точку cool, вы получите ошибку, такую ​​как ошибка сегмента при запуске программы. Если вы используете const char* cool = "cool", вы получите сообщение об ошибке при компиляции, если попытаетесь изменить строку.
Вы можете прочитать эту страницу для получения дополнительной информации http://www.geeksforgeeks.org/storage-for-strings-in-c/