Why strrchr() returns `char*` instead of `const char*`?

白昼怎懂夜的黑 提交于 2019-12-07 02:21:53

问题


The function char* strrchr(const char *str, int ch) returns a pointer (char*) within str (const char *) where the last occurrence of ch is located.

So we can write the following code without any cast:

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

What is the advantage to return char* instead of const char* ?

EDIT:
As a Shafik Yaghmour pointed out, there are very good answers to How does strchr implementation work?

As my code is in C++, I will use <cstring> instead of <string.h>. Thanks for your answers ;-)

However, the Mike Seymour's answer fits best the question. I have even added a more detailed answer below to clearly say as strrchr() is a C function (overload not permitted), the declaration fits both const and non-const strings. Because strrchr() can be called with a non-const string, the returned string should also be non-const.


回答1:


In C, the function must either be like this, or force the user to use dodgy casts in many situations:

  • If it took a non-const pointer, you couldn't search a const string;
  • If it returned a const pointer, you couldn't use it to modify a non-const string.

In C++, you should include <cstring> rather than the deprecated C-only header. That will give you two const-correct overloads, which couldn't be done in C:

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



回答2:


You're looking at the legacy function from the C standard library (<string.h>). The C++ library (<cstring>) introduces appropriate const and non-const overloads, so you should use that wherever possible.




回答3:


const char *str means strrchr guarantees not to modify str.

Returning const char * means strrchr forbids you to modify the returned value.




回答4:


strrchr() from <string.h> is a C function. As C does not permit function overloading, strrchr() has been designed to fit both const and non-const strings.

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

strrchr() may be called with a non-const string, and therefore the returned string should also be non-const as explained in the following examples.

const context without compilation error:

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

non-const context without compilation error:

#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"
}

Bad usage also without compilation error:

#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
}

In C++, there are two overloaded functions:

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

const context uses the 1st one:

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

non-const context uses the 2nd one:

#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"
}

Bad usage should produce compilation error:

#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';
}

But this last example does not produce any compilation error using g++ -Wall file.cpp. Tested using GCC versions 4.1.2 (RedHat) and 4.7.2 (MinGW).




回答5:


Why would you forbid the code from modifying a returned variable? Mind that const char * is not char * const, you would be allowed to modify the character in any case, but you won't have control on the returned value itself, which doesn't make much sense since you could want to change it and edit the underlying string in a different position for your purpose.



来源:https://stackoverflow.com/questions/16860418/why-strrchr-returns-char-instead-of-const-char

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!