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

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

本文关键字:char const 返回 strrchr 为什么      更新时间:2023-10-16

函数char* strrchr(const char *str, int ch)返回str (const char *)中最后一次出现的ch所在的指针(char*)。

因此,我们可以编写以下代码而不进行强制转换:

#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>。谢谢你的回答;-)

然而,Mike Seymour的回答最适合这个问题。我甚至在下面添加了一个更详细的答案,明确地说strrchr()是一个C函数(不允许重载),声明适合const非const字符串。因为strrchr()可以用非const字符串调用,返回的字符串也应该是非const

您正在查看来自C标准库(<string.h>)的遗留函数。c++库(<cstring>)引入了适当的const和非const重载,因此您应该尽可能使用它。

在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);

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

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

来自<string.h>strrchr()是一个C函数。由于C语言不允许函数重载,所以strrchr()被设计成既适合const字符串,也适合非const字符串。

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

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

const context没有编译错误:

#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++中,有两个重载函数:
const char* strrchr( const char* str, int ch );  //1st
      char* strrchr(       char* str, int ch );  //2nd

const context使用第一个:

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

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