Почему strrchr() возвращает `char*` вместо `const char*`?

Функция char* strrchr(const char *str, int ch) возвращает указатель (char*) в str (const char *) где последнее вхождение ch расположен.

Таким образом, мы можем написать следующий код без приведения:

#include <string.h>
int main()
{
    const char CONSTSTR[] = "foo/bar/foobar.txt";
    char *ptr = strrchr (CONSTSTR, '/');
    *ptr++ = 'B';
    *ptr++ = 'A';
    *ptr++ = 'D';
}

В чем преимущество возвращения char* вместо const char*?

РЕДАКТИРОВАТЬ:
Как отметил Shafik Yaghmour, есть очень хорошие ответы на вопрос: Как работает реализация strchr?

Поскольку мой код на C++, я буду использовать <cstring> вместо <string.h>, Спасибо за ваши ответы;-)

Тем не менее, ответ Майка Сеймура лучше всего подходит для вопроса. Я даже добавил более подробный ответ ниже, чтобы четко сказать, как strrchr() является функцией C (перегрузка не разрешена), объявление подходит как для константных, так и для неконстантных строк. Так как strrchr() может вызываться с неконстантной строкой, возвращаемая строка также должна быть неконстантной.

5 ответов

Решение

В Си функция должна быть такой, или заставлять пользователя использовать хитрые приведения во многих ситуациях:

  • Если это занялоconst указатель, вы не можете найти const строка;
  • Если он вернул const указатель, вы не можете использовать его для измененияconst строка.

В C++ вы должны включить <cstring> а не устаревший C-only заголовок. Это даст вам две const-правильные перегрузки, которые не могут быть выполнены в C:

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

Вы смотрите на устаревшую функцию из стандартной библиотеки C (<string.h>). Библиотека C++ (<cstring>) вводит соответствующие const и не const перегрузки, так что вы должны использовать это везде, где это возможно.

const char *str средства strrchr гарантирует не изменять str,

возврате const char * средства strrchr запрещает вам изменять возвращаемое значение.

strrchr() от<string.h> является функцией C. Поскольку C не разрешает перегрузку функций, strrchr() был разработан для соответствия как константным, так и неконстантным строкам.

char* strrchr( const char *str, int ch );

strrchr() может вызываться с неконстантной строкой, и поэтому возвращаемая строка также должна быть неконстантной, как объяснено в следующих примерах.

const context без ошибки компиляции:

#include <string.h>
int main()
{
    const char CONSTSTR[] = "foo/bar/foobar.txt";
    const char *basename = strrchr (CONSTSTR, '/');
    // basename points to "foobar.txt"
}

неконстантный контекст без ошибки компиляции:

#include <string.h>
int main()
{
    char nonconst[] = "foo/bar/foobar.txt";
    char *basename = strrchr (nonconst, '/');
    basename[0] = 'G';
    basename[3] = 'D';
    // basename points to "GooDar.txt"
}

Неправильное использование также без ошибки компиляции:

#include <string.h>
int main()
{
    const char CONSTSTR[] = "foo/bar/foobar.txt";
    char *nonconst = strrchr (CONSTSTR, '/');
    *nonconst++ = 'B';
    *nonconst++ = 'A';  // drawback of the unique declaration: 
    *nonconst++ = 'D';  // no compilation error
}

В C++ есть две перегруженные функции:

const char* strrchr( const char* str, int ch );  //1st
      char* strrchr(       char* str, int ch );  //2nd

const context использует 1-й:

#include <cstring>
int main()
{
    const char CONSTSTR[] = "foo/bar/foobar.txt";
    const char *basename = std::strrchr (CONSTSTR, '/');
    // basename points to "foobar.txt"
}

неконстантный контекст использует 2-й:

#include <cstring>
int main()
{
    char nonconst[] = "foo/bar/foobar.txt";
    char *basename = std::strrchr (nonconst, '/');
    basename[0] = 'G';
    basename[3] = 'D';
    // basename points to "GooDar.txt"
}

Неправильное использование должно привести к ошибке компиляции:

#include <cstring>
int main()
{
    const char CONSTSTR[] = "foo/bar/foobar.txt";

    char *nonconst = std::strrchr (CONSTSTR, '/');
// Visual C++ v10 (2010)
// error C2440: 'initializing' : cannot convert from 'const char *' to 'char *'

    *nonconst++ = 'B';
    *nonconst++ = 'A';
    *nonconst++ = 'D';
}

Но этот последний пример не приводит к ошибке компиляции, используя g++ -Wall file.cpp, Протестировано с использованием версий GCC 4.1.2 (RedHat) и 4.7.2 (MinGW).

Почему вы запрещаете коду изменять возвращаемую переменную? Имейте в виду, что const char * не является char * const, вам будет разрешено изменить символ в любом случае, но вы не сможете контролировать само возвращаемое значение, что не имеет особого смысла, так как вы можете изменить его и отредактировать основную строку в другой позиции для твоя цель.

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