我试图编写自己的strhr()方法实现。
现在看起来是这样的:

char *mystrchr(const char *s, int c) {
    while (*s != (char) c) {
        if (!*s++) {
            return NULL;
        }
    }
    return (char *)s;
}

最后一行原来是
return s;

但这没用,因为S是康斯特。我发现需要这个演员,但我真的不知道我在那里做什么:(有人能解释一下吗?

最佳答案

我认为这实际上是c标准对strchr()函数定义的一个缺陷。(我很高兴被证明是错的。)(回复评论,这是否真的是一个缺陷是有争议的;但这仍然是一个糟糕的设计。它可以安全使用,但不安全使用太容易。)
C标准是这样说的:

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

strhr函数定位c的第一个出现
(转换为字符)由s指向的字符串中。
终止空字符被视为字符串的一部分。
这意味着这个程序:
#include <stdio.h>
#include <string.h>

int main(void) {
    const char *s = "hello";
    char *p = strchr(s, 'l');
    *p = 'L';
    return 0;
}

尽管它小心地将指向字符串文本的指针定义为指向constchar的指针,但它具有未定义的行为,因为它修改了字符串文本。gcc至少没有对此发出警告,程序会因分段错误而终止。
问题是strchr()接受一个const char*参数,这意味着它承诺不会修改s指向的数据——但它返回一个普通的char*,这允许调用者修改相同的数据。
下面是另一个例子;它没有未定义的行为,但是它悄悄地修改了一个const限定对象,而没有任何类型转换(进一步考虑,我相信它有未定义的行为):
#include <stdio.h>
#include <string.h>

int main(void) {
    const char s[] = "hello";
    char *p = strchr(s, 'l');
    *p = 'L';
    printf("s = \"%s\"\n", s);
    return 0;
}

这意味着,我认为(为了回答您的问题),c实现strchr()必须转换其结果以将其从const char*转换为char*,或者做一些等效的事情。
这就是为什么C++在对C标准库进行的少数改动中,用相同名称的两个重载函数替换了cc:
const char * strchr ( const char * str, int character );
      char * strchr (       char * str, int character );

当然C不能这么做。
另一种方法是将strchr()替换为两个函数,一个使用astrchr并返回aconst char*,另一个使用aconst char*并返回achar*。与C++不同,这两个函数必须有不同的名称,可能是char*strchr
(历史上,strcchr是在定义了const之后添加到c中的。这可能是在不破坏现有代码的情况下保持strchr()的唯一方法。
strchr()不是唯一有此问题的c标准库函数。受影响函数的列表(我认为这个列表是完整的,但我不能保证)是:
void *memchr(const void *s, int c, size_t n);
char *strchr(const char *s, int c);
char *strpbrk(const char *s1, const char *s2);
char *strrchr(const char *s, int c);
char *strstr(const char *s1, const char *s2);

(均在strchr()中声明)和:
void *bsearch(const void *key, const void *base,
    size_t nmemb, size_t size,
    int (*compar)(const void *, const void *));

(在<string.h>中声明)。所有这些函数都接受指向指向数组初始元素的<stdlib.h>数据的指针,并返回指向该数组元素的非-const指针。

10-07 19:28