Почему стандартная библиотечная функция C `strchr` возвращает указатель на неконстантный, если в качестве первого аргумента указан`const char * '?

Компиляция данного примера кода с помощью gcc/g++ успешно завершена. Там нет ошибки для strchr вызов, который явно назначает const char * в char *,

я обнаружил strchr объявлен как char * strchr(const char *, int) на двух разных источниках pubs.opengroup.org и cplusplus.com

Если strchr реализован так, чтобы отбрасывать постоянство, тогда почему это так?

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

Можете ли вы дать более подробное объяснение по этому поводу.

#include <string.h>

int main () {
    const char *str = "Sample string";
    char * ptr;

    //ptr = str;            //  Error: discards const qualifier - both on gcc and g++
    pch = strchr(str,'S');  //  Succeeds in assigning <const char *> to <char *>

    *pch = '4';             //  Runtime error: segmentation fault

    return 0;
}

Пробовал на Win7, используя MSYS2/mingw-w64 gcc_v5.3.0 и TDM-gcc32 v5.1.0 .

1 ответ

Решение

Когда вы звоните strchr с char* ты хочешь char* обратно, так что вам не нужно делать бросок на результат. C не поддерживает перегрузку функций, поэтому то же самое strchr Функция используется для поиска в char* и в const char*, Он возвращает неконстантный указатель во всех случаях. Если вы называете это с const char* это в основном отбрасывает const так что вызывающие абоненты обязаны использовать его безопасно (например, присваивая результат const char* немедленно, чтобы избежать небезопасного использования возвращаемого указателя).

Если бы целью было предоставить функцию, которая работает как со строками char *, так и со строками char * - это можно было бы реализовать с использованием двух разных имен функций.

Да, это могло быть, но это не так. Оригинальная версия C не поддерживает const так что программист всегда должен был избегать попыток изменить строковые литералы. Если бы использовались разные имена функций, то это нарушило бы существующий код, который использовал strchr безопасно. Это замедлило бы принятие нового const ключевое слово, если традиционный C-код, подобный этому, внезапно перестал компилироваться:

char arr[] = "foo bar";
*strchr(arr, 'r') = 'z';

"Дух C" заключается в том, что он не пытается помешать вам делать небезопасные вещи, это ваша работа - писать правильный код.

В C++ strchr перегружен для сохранения постоянства:

char* strchr(char*, int);
const char* strchr(const char*, int);

Это означает, что он автоматически делает правильные вещи, и гораздо сложнее случайно написать небезопасный код с strchr,

Другие вопросы по тегам