如何和strchr执行工作 [英] How does strchr implementation work
问题描述
我试着写我自己的实施和strchr()方法。
现在看起来是这样的:
的char * mystrchr(为const char * S,诠释三){
而(* S!=(char)的C){
如果(!* S ++){
返回NULL;
}
}
回报(字符*)S;
}
最后一行原本是
返回小号;
但这并没有工作,因为s是常数。我发现,需要有这个转换(字符*),但我真的不知道我在做什么有:(有人能解释一下吗?
我认为这实际上是在和strchr()
函数的C标准的定义的一个漏洞。 (我很乐意被证明是错误的。)(回复的意见,这是值得商榷的是否真的是一个缺陷。恕我直言,它仍然是设计不良它的可以的安全使用,但它太容易不安全使用)。
下面是C标准说的话:
的char *和strchr(为const char * S,INT C);
在和strchr 功能定位中第一次出现的 C
通过的取值(转换为字符)字符串中指出。该
终止空字符被认为是字符串的一部分。
块引用>这意味着,此程序:
的#include<&stdio.h中GT;
#包括LT&;&string.h中GT;诠释主要(无效){
为const char * s =你好;
的char * p =和strchr(S,'L');
* p值=L;
返回0;
}即使仔细定义指向字符串为
常量
,是未定义的行为,因为它修改字符串。 GCC,至少,没有警告这一点,并且程序段故障死亡。问题是,
和strchr()
需要为const char *
的说法,这意味着它承诺不修改该数据取值
点 - 但它返回一个纯的char *
,允许调用者修改同一数据。下面是另一个例子; <击>它不具有不确定的行为,但击>它悄悄地修改了
常量
限定的对象没有任何强制类型转换(其中,在进一步的思考,我相信是未定义行为):的#include&LT;&stdio.h中GT;
#包括LT&;&string.h中GT;诠释主要(无效){
为const char S [] =你好;
的char * p =和strchr(S,'L');
* p值=L;
的printf(S = \\%s \\的\\ N,S);
返回0;
}这意味着,我认为,(回答你的问题)的
和strchr的C实现()
有投它的结果将其从为const char *
到的char *
,或做一些相当于这也是为什么C ++,在它对C标准库中的一些变化之一,替换
和strchr()
通过两个同名的重载函数:为const char *和strchr(为const char * str中,诠释人物);
字符*和strchr(的char * str中,诠释人物);当然的C无法做到这一点。
另一种做法是由两个功能,一是采取了
为const char *
键,返回到替换和strchr
返回
的char * $为const char *
,另外服用的char *
和C $ C>。不像在C ++中,这两个函数就必须有不同的名称,也许和strchr
和strcchr
。(从历史上看,
常量
已在和strchr()
已经定义添加到C,这是可能的只有这样,才能保持和strchr()
不打破现有code)
和strchr()
是不是有这个问题的唯一C标准库函数。受影响的功能(我的认为的这份名单是完整的,但我不保证它)的列表是:void *的了memchr(常量无效* S,INT C,为size_t n)的;
字符*和strchr(为const char * S,INT C);
的char * strpbrk(为const char * S1,为const char * S2);
的char * strrchr(为const char * S,INT C);
字符*的strstr(为const char * S1,为const char * S2);(全部在声明
&LT;&string.h中GT;
)和的void * bsearch(常量无效*键,常量无效*基地,
为size_t nmemb个,为size_t大小,
INT(* COMPAR)(常量无效*,常量无效*));(在
&LT宣布;文件stdlib.h&GT;
)。所有这些功能需要一个指向常量
指向数组的初始元素的数据,并返回一个非 -常量
指针指向数组的元素I tried to write my own implementation of the strchr() method.
It now looks like this:
char *mystrchr(const char *s, int c) { while (*s != (char) c) { if (!*s++) { return NULL; } } return (char *)s; }
The last line originally was
return s;
But this didn't work because s is const. I found out that there needs to be this cast (char *), but I honestly don't know what I am doing there :( Can someone explain?
解决方案I believe this is actually a flaw in the C Standard's definition of the
strchr()
function. (I'll be happy to be proven wrong.) (Replying to the comments, it's arguable whether it's really a flaw; IMHO it's still poor design. It can be used safely, but it's too easy to use it unsafely.)Here's what the C standard says:
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.
Which means that this program:
#include <stdio.h> #include <string.h> int main(void) { const char *s = "hello"; char *p = strchr(s, 'l'); *p = 'L'; return 0; }
even though it carefully defines the pointer to the string literal as
const
, has undefined behavior, since it modifies the string literal. gcc, at least, doesn't warn about this, and the program dies with a segmentation fault.The problem is that
strchr()
takes aconst char*
argument, which means it promises not to modify the data thats
points to -- but it returns a plainchar*
, which permits the caller to modify the same data.Here's another example;
it doesn't have undefined behavior, butit quietly modifies aconst
qualified object without any casts (which, on further thought, I believe has undefined behavior):#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; }
Which means, I think, (to answer your question) that a C implementation of
strchr()
has to cast its result to convert it fromconst char*
tochar*
, or do something equivalent.This is why C++, in one of the few changes it makes to the C standard library, replaces
strchr()
with two overloaded functions of the same name:const char * strchr ( const char * str, int character ); char * strchr ( char * str, int character );
Of course C can't do this.
An alternative would have been to replace
strchr
by two functions, one taking aconst char*
and returning aconst char*
, and another taking achar*
and returning achar*
. Unlike in C++, the two functions would have to have different names, perhapsstrchr
andstrcchr
.(Historically,
const
was added to C afterstrchr()
had already been defined. This was probably the only way to keepstrchr()
without breaking existing code.)
strchr()
is not the only C standard library function that has this problem. The list of affected function (I think this list is complete but I don't guarantee it) is: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);
(all declared in
<string.h>
) and:void *bsearch(const void *key, const void *base, size_t nmemb, size_t size, int (*compar)(const void *, const void *));
(declared in
<stdlib.h>
). All these functions take a pointer toconst
data that points to the initial element of an array, and return a non-const
pointer to an element of that array.这篇关于如何和strchr执行工作的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!