c - strchr 实现如何工作

标签 c pointers constants strchr

我尝试编写自己的 strchr() 方法实现。

现在看起来像这样:

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

最后一行原本是

return s;

但这不起作用,因为 s 是常量。我发现需要这个类型转换 (char *),但老实说我不知道​​我在那里做什么 :( 有人可以解释一下吗?

最佳答案

我相信这实际上是 C 标准对 strchr() 的定义中的一个缺陷。功能。 (我会很高兴被证明是错误的。)(回复评论,它是否真的是一个缺陷是有争议的;恕我直言,它仍然是糟糕的设计。它可以安全地使用,但它太容易了不安全地使用它。)

这是 C 标准所说的:

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

The strchr function locates the first occurrence of c (converted to a char) in the string pointed to by s. The terminating null character is considered to be part of the string.

这意味着这个程序:

#include <stdio.h>
#include <string.h>

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

尽管它小心地将指向字符串文字的指针定义为指向 const 的指针 char , 具有未定义的行为,因为它修改了字符串文字。至少 gcc 不会对此发出警告,程序会因段错误而终止。

问题是 strchr()需要 const char*参数,这意味着它 promise 不会修改 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;
}

这意味着,我认为(回答您的问题)strchr() 的 C 实现必须将其结果转换为 const char*char* ,或做一些等效的事情。

这就是为什么 C++ 在对 C 标准库所做的少数更改之一中替换了 strchr()。具有两个同名的重载函数:

const char * strchr ( const char * str, int character );
      char * strchr (       char * str, int character );

C当然做不到。

替代方案是替换 strchr通过两个函数,一个取 const char*并返回 const char* , 另一个服用 char*并返回 char* .与 C++ 不同,这两个函数必须具有不同的名称,可能是 strchr。和 strcchr .

(历史上,const 是在定义了 strchr() 之后添加到 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);

(全部在 <string.h> 中声明)和:

void *bsearch(const void *key, const void *base,
    size_t nmemb, size_t size,
    int (*compar)(const void *, const void *));

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

关于c - strchr 实现如何工作,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14367727/

相关文章:

c++ - 为什么不能在静态成员函数中使用const成员呢?

c - 理解指向结构的指针是指访问它时c中的指针成员

C++:访问作为函数参数传递的双指针数组指向的变量值

c - Travis CI 使用非 perl 语言安装 perl 模块

c# - C# 中的不安全指针/数组表示法

复制/分配 char * 指针数据

c++ - 静态常量对象

Objective-C – 使用包含其名称的字符串访问 extern const?

c - 从一个字节中读取 'N' 位

c - make 文件,这样看起来可以吗?