Как возвращение strstr не является константой
Стандартная функция strstr
используется для определения местоположения подстроки в строке. Оба аргумента функции имеют тип const char *
, но тип возврата char *
.
Я хотел бы знать, как реализована стандартная функция, нарушающая const-правильность.
Ответы
Ответ 1
C позволяет указывать на память с константными или неконстантными указателями, независимо от того, был ли объект определен с помощью определителя константы или нет.
6.5 Выражения
- Объект должен иметь сохраненное значение, доступ к которому имеет только выражение lvalue, которое имеет один из следующие типы:
- квалифицированная версия типа, совместимая с эффективным типом объекта,
Прототипом strstr в C является:
char *strstr(const char *s1, const char *s2);
Возвращаемый указатель, если он действителен, указывает на строку s1. Это может быть достигнуто с помощью cast:
const char safe = 's' ;
char* careful = ( char* )&safe ;
Проблема заключается в изменении этой памяти.
6.7.3 Типовые классификаторы
- Если предпринимается попытка изменить объект, определенный с использованием типа const, используя lvalue с неконстантно-квалифицированным типом, поведение undefined.
Поскольку вы создали строку, вы должны знать, можете ли вы ее изменить или нет, поэтому вы можете принять возвращаемое значение с указателем на const, чтобы избежать каких-либо проблем:
const char* find = strstr( ... ) ;
Ответ 2
Все const char *
сообщают вам, что strstr
не собирается изменять строку, которую вы передаете в нее.
Если вы измените возвращаемую строку или нет, это зависит от вас, так как это ваша строка!
В С++ это было изменено перегрузкой метода и наличием двух версий, входная версия const
имеет выход const
.
В C он не имеет такого уровня безопасности, который встроен для вас, и предполагает, что вы знаете, следует ли вам изменять возвращаемую строку.
Ответ 3
В соответствии с ISO С++ 21.8 (7) strstr
возвращает a const char*
или char*
в зависимости от того, получает ли он const char*
или char*
.
const char* strstr(const char* s1, const char* s2);
char* strstr( char* s1, const char* s2);
Ответ 4
Это делается путем указания подписи и оставления реализации до компиляторов.
Обратите внимание, что возвращение a char*
, указывающее на строку const char[]
, просто опасно, но еще не является нарушением какого-либо правила. Однако любая попытка записать в эту память по-прежнему Undefined Поведение.
Ответ 5
Функция strstr
восходит к эпохе, прежде чем появилась такая вещь, как указатель const
. В случаях было бы законным для того, чтобы код записывал в память, идентифицированный первым указателем, переданным в strstr
, было бы законным для того, чтобы код записывал в память, идентифицированную возвращенным указателем, и в тех случаях, когда возвращаемое значение было бы используется в путях, которые были законными с указателем на постоянную память (например, строковый литерал), можно было законным образом передать такой указатель на strstr
.
Если сегодня была определена функциональность, аналогичная strstr
, она может быть реализована с использованием двух методов: один из которых может принимать любой указатель и возвращать указатель, который не может быть написан получателем, и один из них только принимать записываемые указатели, но возвращать указатель, который получатель мог бы использовать по своему усмотрению. Потому что для некоторого кода, который использовал strstr
, нужно было бы использовать указатели только для чтения, а потому, что для некоторого кода, который использовал strstr
, нужно было писать указатели, которые он мог бы дать при задании записываемых указателей, имеют один набор квалификаций указателя в обоих направлениях. Следствием этого является набор квалификаций указателей, которые на самом деле не являются "безопасными" [поскольку он может возвращать записываемый указатель на область памяти только для чтения), и это позволит компиляции кода в некоторых случаях, когда это действительно "не должно", но который позволит коду, написанному до дней указателей const
, продолжить работу по назначению.
Ответ 6
С++ содержит две версии, которые принимают аргументы const и те, которые принимают неконстантные.
const char* strstr( const char* str, const char* target );
char* strstr( char* str, const char* target );
Так как в C мы не можем перегружать, мы оставляем два неприятных варианта:
- Либо мы принимаем аргументы как неконстантные, но если наши источники действительно являются константами, нам нужно выполнить неприятный перенос в неконстантный.
- Второй вариант - это тот, который мы имеем, что мы принимаем аргументы как const, но возвращаем не const. Мы могли бы вернуть const char *, но тогда мы не смогли бы изменить результат.
Ответ 7
Возвращаемое значение не является переменной, которую вы передали функции как параметр. Эта функция возвращает указатель на первое вхождение в стоге сена любой из последовательности символов, указанных в игле, или нулевой указатель, если последовательность не присутствует в стоге сена.