Вопрос почти в заголовке.
Код
void modify_str(char* str){
if (strlen(str) > 5) {
str[5] = 'x';
}
}
Вызывает неопределенное поведение, если в качестве аргумента передается строковый литерал, то есть:
modify_str("some text");
Или
char *str = "some text";
modify_str(str);
Есть ли способ утверждать во время выполнения, что строка, переданная в качестве аргумента, является не строковым литералом, а изменяемой строкой?
Строковые литералы в C имеют тип char []
, поэтому нет стандартного способа сделать это.
Однако некоторые компиляторы имеют флаги, которые могут изменить тип строковых литералов на const char []
, чтобы вы получали предупреждение о таком коде.
Если вы используете gcc, добавьте флаг -Wwrite-strings
, чтобы строковые литералы имели тип const char []
. Тогда вы получите такое предупреждение:
x1.c: In function ‘main’:
x1.c:14:16: warning: passing argument 1 of ‘modify_str’ discards ‘const’ qualifier from pointer target type [-Wdiscarded-qualifiers]
modify_str("some text");
^~~~~~~~~~~
x1.c:4:23: note: expected ‘char *’ but argument is of type ‘const char *’
void modify_str(char* str){
~~~~~~^~~
Затем в сочетании с -Werror=discarded-qualifiers
мы даже получаем ошибку от...
Самый переносимый способ сделать это — всегда сначала назначать литерал указателю const char *
и передавать его в качестве аргумента. Вы получите предупреждение на большинстве компиляторов по умолчанию без каких-либо специальных флагов. Например. const char *pArg = "some text"; modify_str(pArg);
Присвоение константе, безусловно, является хорошей упреждающей мерой, но параметры компилятора — хороший способ заставить вас (и всех, кто касается кода) принять эту меру.
@anastaciu Просто объявите указатели на строковые литералы с квалификатором const.