strstr return 如何不是一个常数

Posted

技术标签:

【中文标题】strstr return 如何不是一个常数【英文标题】:How strstr return is not a constant 【发布时间】:2015-04-23 14:49:19 【问题描述】:

标准函数strstr用于查找字符串中子字符串的位置。函数的两个参数都是const char *类型,但返回类型是char *

我想知道一个标准函数是如何实现违反 const 正确性的。

【问题讨论】:

你包括cstring,而不是string.h?否则,您使用的是 C 版本 - 天知道他们在做什么。如果第一个参数也是非const char*,则 C++ std::strstr 版本仅返回 char*。见here。 (抱歉 - 刚刚也注意到了 C 标记……您实际使​​用的是哪种语言?) @TonyD C 版本是char * strstr ( const char *, const char * ); 注意C++中two overloads of strstr有一个带const char*参数,一个带普通char*,返回值如下。 如果问题不是关于差异、相似之处、编写可在两种语言中运行的代码或在另一种语言中使用一种语言的函数时,请不要将 C 和 C++ 标记用于同一问题。跨度> 【参考方案1】:

所有const char * 告诉你的是strstr 不会修改你传递给它的字符串。

是否修改返回的字符串由您决定,因为它是您的字符串!

在 C++ 中,这已通过重载方法并具有两个版本进行了更改,const 输入版本具有 const 输出。

在 C 语言中,它没有为您内置的安全级别,并假设您知道自己是否应该修改返回的字符串。

【讨论】:

C 没有的实际上是函数重载。如果该函数最初是在 C++ 中引入的,它可能有两种形式,const 和 non-const。但是这个函数最早是在C中引入的,而且是在K&R时代引入的,当时还没有const关键字。【参考方案2】:

C 允许使用 const 或非 const 指针指向内存,无论对象是否使用 const 限定符定义。

6.5 表达式

    对象的存储值只能由具有以下之一的左值表达式访问 以下类型:

——与对象的有效类型兼容的类型的限定版本,

strstr在C中的原型是:

char *strstr(const char *s1, const char *s2);

如果有效,返回的指针指向字符串 s1。这可以通过演员来实现:

const char safe = 's' ;
char* careful = ( char* )&safe ;

问题在于修改该内存。

6.7.3 类型限定符

    如果尝试通过使用来修改使用 const 限定类型定义的对象 具有非 const 限定类型的左值,行为未定义。

既然你创建了字符串,你应该知道你是否可以修改它,因此你可以接受带有指向 const 的指针的返回值,以避免任何问题:

const char* find = strstr( ... ) ;

【讨论】:

【参考方案3】:

根据 ISO C++ 21.8(7) strstr 返回 const char*char*,具体取决于它是否获得 const char*char*

const char* strstr(const char* s1, const char* s2);

char* strstr( char* s1, const char* s2);

【讨论】:

这对 C++ 来说是正确的,但在 C99 标准中 strstr 返回 char* 我首先看到了 C++ 标签,所以我使用了 C++ 标准。您对 C 标准的看法是正确的。【参考方案4】:

这是通过指定签名来完成的,并将实现留给编译器构建者。

请注意,返回指向const char[] 字符串的char* 是危险的,但还没有违反任何规则。但是,任何写入该内存的尝试仍然是未定义的行为。

【讨论】:

【参考方案5】:

strstr 函数可以追溯到没有const 指针之类的东西之前的时代。如果代码写入由传递给strstr的第一个指针标识的内存是合法的,代码写入由返回的指针标识的内存是合法的,并且在返回值仅是的情况下以合法的方式使用指向只读内存的指针(例如字符串文字),可以合法地将这样的指针传递给strstr

如果今天定义了类似于strstr 的功能,它可能会使用两种方法来实现——其中一种可以接受任何指针并返回接收者无法写入的指针,其中一种会只接受可写指针,但会返回一个指针,收件人可以根据需要使用它。然而,因为使用strstr 的一些代码需要传递只读指针,并且因为一些使用strstr 的代码需要能够写入在给定可写指针时会产生的指针,所以有必要有一组指针资格可以双向工作。结果是一组不是真正“安全”的指针限定[因为它可能返回指向内存只读区域的可写指针],并且在某些“不应该”的情况下允许代码编译,但这将允许在const 指针之前编写的代码继续按预期工作。

【讨论】:

【参考方案6】:

C++ provides two versions 一个接受 const 参数和一个接受非 const 参数。

const char* strstr( const char* str, const char* target );      
char* strstr(       char* str, const char* target );

由于在 C 中我们不能重载,所以我们有两个不愉快的选择:

我们要么将参数视为非常量,但如果我们的源确实是常量,那么我们需要执行不愉快的转换为非常量。 第二个选项是我们拥有的选项,即我们将参数作为 const 但我们返回一个非常量。我们可以返回一个 const char*,但我们永远无法修改结果。

【讨论】:

【参考方案7】:

返回值不是你作为参数传递给函数的变量。该函数返回一个指针,指向在 needle 指定的整个字符序列中第一次出现在 haystack 中的任何字符,如果 haystack 中不存在该序列,则返回空指针。

【讨论】:

它仍然与它相关(作为相同数组声明或内存分配的一部分),因此如果正确使用该函数,几乎可以肯定它与 haystack 具有相同的“适当的 const-ness”。

以上是关于strstr return 如何不是一个常数的主要内容,如果未能解决你的问题,请参考以下文章

leetcode 28. Implement strStr() 实现strStr()

LeetCode 28: Implement Strstr

028. Implement strStr()

刷题之Implement strStr()

leetcode 28. 实现strStr()

Leetcode028. Implement strStr()