为什么strrchr()返回' char* '而不是' const char* ' ?
Why strrchr() returns `char*` instead of `const char*`?
函数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
,您将被允许在任何情况下修改字符,但您将无法控制返回值本身,这没有多大意义,因为您可能想要更改它并根据您的目的在不同位置编辑基础字符串。
- 在字符串函数中抛出'char const*'实例后调用的终止
- 双重标准?为什么只有 char* const&a = "bla" 的警告?
- 包括"lvtocon.h",未定义对'operator<<(std::ostream&, char const*)的引用
- 为什么 const char* const & = 可以编译"hello"?
- 将字符串文本常量定义为 char const* 和 wchar const*
- 如何将std::wstring转换为char const[]
- "char const * name() const _WEBSOCKETPP_NOEXCEPT_TOKEN_ {"剂量是什么意思
- 使用提升对字符串进行标记化时,将令牌转换为 char* const* 时失败
- 如何从 std::initializer_list<char const* 构建 std::vector<std::string>>
- 将 std::vector<std::string> 转换为 const char* const*
- 引发"char const*"错误的实例后调用的终止
- 将const char * const参数成员分配给新值
- 从'const char**'到'char* const*'的转换无效
- 从 sub_match<常量字符 *>' 转换为'const char *const &'
- char*const和constchar*之间有什么区别?(重复-需要更多澄清)
- 使用工厂方法时编译器错误:无法转换"const std::p air<char* const
- HEVC 解码器端口 Android 警告:从 'signed char*' 到 'char const* 的转换无效*
- 如何从'char const*'中删除常量
- 'char const *str'作为模板参数
- 为什么不;t strlen(.)应为const char*const str,而不是const char*