为什么strrchr()返回`char *`而不是`const char *`?

时间:2013-05-31 15:06:38

标签: c++ null-terminated strrchr const-string

函数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指出的那样,How does strchr implementation work?

有很好的答案

由于我的代码是用C ++编写的,我将使用<cstring>代替<string.h>。谢谢你的回答; - )

然而,Mike Seymour's answer最适合这个问题。我甚至添加了a more detailed answer below来清楚地说明strrchr()是一个C函数(不允许重载),该声明适用于 const 非const 字符串。因为可以使用非const 字符串调用strrchr(),所以返回的字符串也应该是非const

5 个答案:

答案 0 :(得分:13)

您正在查看C标准库(<string.h>)中的遗留函数。 C ++库(<cstring>)引入了appropriate const and non-const overloads,因此您应该尽可能使用它。

答案 1 :(得分:6)

在C中,函数必须像这样,或强迫用户在许多情况下使用狡猾的强制转换:

  • 如果使用非const指针,则无法搜索const字符串;
  • 如果它返回const指针,则无法使用它来修改非const字符串。

在C ++中,您应该包含<cstring>而不是已弃用的仅限C的标头。这将为您提供两个const-correct重载,无法在C中完成:

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

答案 2 :(得分:3)

const char *str表示strrchr保证不修改str

返回const char *表示strrchr禁止修改返回的值。

答案 3 :(得分:2)

strrchr() from <string.h>是一个C函数。由于C不允许函数重载,strrchr()被设计为适合 const 非const 字符串。

char* strrchr( const char *str, int ch );
可以使用非const 字符串调用

strrchr(),因此返回的字符串也应该是非const ,如以下示例中所述。

const 上下文没有编译错误:

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

非const 上下文,没有编译错误:

#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 ++中,有two overloaded functions

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

const 上下文使用第一个:

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

非const 上下文使用第二个:

#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)进行测试。

答案 4 :(得分:0)

为什么要禁止代码修改返回的变量?请注意const char *不是char * const,你可以在任何情况下修改角色,但是你无法控制返回的值本身,这没有多大意义,因为你可以想要更改它并根据您的目的在不同的位置编辑基础字符串。