如何实现strstr()而不抛弃const?

时间:2022-09-10 23:23:11

strstr is a C99-conforming function, the type signature of which is the following:

strstr是符合C99的函数,其类型签名如下:

char *strstr(const char *haystack, const char *needle);

Is it possible to implement this function without casting away a const somewhere?

是否可以实现此功能而无需在某处丢弃const?

For reference, here is Apple's implementation, and here is GNU's implementation. Both cast away the const at the end.

作为参考,这是Apple的实现,这里是GNU的实现。两人最后都抛弃了const。

2 个解决方案

#1


9  

You can't implement strstr() without violating const correctness somehow. A cast is the most straightforward way to do that. You can probably hide the violation somehow (for example you could use memcpy() to copy the pointer value), but there's no point in doing so.

你不能以某种方式实现strstr()而不违反const正确性。演员阵容是最直接的方式。您可以以某种方式隐藏违规(例如,您可以使用memcpy()来复制指针值),但这样做没有意义。

The problem is that strstr() takes a const char* that points to a string, and returns a non-const char* that points into the same string.

问题是strstr()接受一个指向字符串的const char *,并返回指向同一字符串的非const char *。

For example, this program:

例如,这个程序:

#include <stdio.h>
#include <string.h>
int main(void) {
    const char s[] = "hello";
    char *result = strstr(s, "hello");
    *result = 'H';
    puts(result);
}

modifies (or at least attempts to modify) a const-qualified object, without using a pointer cast or any other obviously unsafe construct.

修改(或至少尝试修改)const限定对象,而不使用指针强制转换或任何其他明显不安全的构造。

Back in 1989, the ANSI C committee could have avoided this problem by defining two different functions, say:

早在1989年,ANSI C委员会就可以通过定义两个不同的功能来避免这个问题,例如:

const char *strcstr(const char *haystack, const char *needle);
      char *strstr (      char *haystack, const char *needle);

one that returns a pointer to a const char given a const arguments, and another that returns pointer to a modifiable char given a modifiable argument. (C++, which inherits the C standard library, does this by overloading.)

一个在给定const参数的情况下返回指向const char的指针,另一个在给定可修改参数的情况下返回指向可修改char的指针。 (C ++,它继承了C标准库,通过重载来实现这一点。)

strstr() is one of several standard string functions that have this problem.

strstr()是出现此问题的几个标准字符串函数之一。

#2


0  

What you are seeing in case of strstr (and some other standard functions) is an idiomatic solution, whose intent is to support non-modifying operations on both const and non-const strings with a single function.

在strstr(以及一些其他标准函数)的情况下,您看到的是一个惯用的解决方案,其目的是支持使用单个函数对const和非const字符串进行非修改操作。

Yes, in order to implement such a function it necessary to explicitly cast away constness from the input pointer. Note that the cast by itself does not yet physically violate anything (meaning: it does not attempt to modify constant data and does not cause undefined behavior). Yet, it does open the door to such violations by returning a non-const pointer to const data to the caller, i.e. violates the conceptual rules of const-correctness.

是的,为了实现这样的功能,必须从输入指针显式地抛弃constness。请注意,强制转换本身并未实际违反任何内容(意思是:它不会尝试修改常量数据,也不会导致未定义的行为)。然而,它确实通过向const调用者返回一个非const指针来打开这种违规行为的大门,即违反了const-correctness的概念规则。

An alternative solution would be to provide two versions of the same standard function - a const one and a non-const one - but without C++-style function overloading this would require two distinctive function names, which does not necessarily look like a very good idea (and even with C++-style function overloading it has its issues too).

另一种解决方案是提供相同标准函数的两个版本 - 一个const和一个非const - 但没有C ++ - 样式函数重载这将需要两个独特的函数名称,这看起来不一定是一个非常好的主意(即使使用C ++风格的函数重载它也有它的问题)。

In this case it is effectively the responsibility of the caller to receive the result into a pointer of the same type as the one that was passed in as an argument. If the argument pointer was const-qualified, it is a very good programming practice to receive the result into a pointer that is const-qualified as well. As long as this guideline is observed, this idiom actually feels right at home in the realm of C language.

在这种情况下,调用者实际上有责任将结果接收到与作为参数传入的指针类型相同的指针中。如果参数指针是const限定的,那么将结果接收到const限定的指针是一种非常好的编程习惯。只要遵守这个指导原则,这个习惯用法在C语言领域实际上就像在家一样。

#1


9  

You can't implement strstr() without violating const correctness somehow. A cast is the most straightforward way to do that. You can probably hide the violation somehow (for example you could use memcpy() to copy the pointer value), but there's no point in doing so.

你不能以某种方式实现strstr()而不违反const正确性。演员阵容是最直接的方式。您可以以某种方式隐藏违规(例如,您可以使用memcpy()来复制指针值),但这样做没有意义。

The problem is that strstr() takes a const char* that points to a string, and returns a non-const char* that points into the same string.

问题是strstr()接受一个指向字符串的const char *,并返回指向同一字符串的非const char *。

For example, this program:

例如,这个程序:

#include <stdio.h>
#include <string.h>
int main(void) {
    const char s[] = "hello";
    char *result = strstr(s, "hello");
    *result = 'H';
    puts(result);
}

modifies (or at least attempts to modify) a const-qualified object, without using a pointer cast or any other obviously unsafe construct.

修改(或至少尝试修改)const限定对象,而不使用指针强制转换或任何其他明显不安全的构造。

Back in 1989, the ANSI C committee could have avoided this problem by defining two different functions, say:

早在1989年,ANSI C委员会就可以通过定义两个不同的功能来避免这个问题,例如:

const char *strcstr(const char *haystack, const char *needle);
      char *strstr (      char *haystack, const char *needle);

one that returns a pointer to a const char given a const arguments, and another that returns pointer to a modifiable char given a modifiable argument. (C++, which inherits the C standard library, does this by overloading.)

一个在给定const参数的情况下返回指向const char的指针,另一个在给定可修改参数的情况下返回指向可修改char的指针。 (C ++,它继承了C标准库,通过重载来实现这一点。)

strstr() is one of several standard string functions that have this problem.

strstr()是出现此问题的几个标准字符串函数之一。

#2


0  

What you are seeing in case of strstr (and some other standard functions) is an idiomatic solution, whose intent is to support non-modifying operations on both const and non-const strings with a single function.

在strstr(以及一些其他标准函数)的情况下,您看到的是一个惯用的解决方案,其目的是支持使用单个函数对const和非const字符串进行非修改操作。

Yes, in order to implement such a function it necessary to explicitly cast away constness from the input pointer. Note that the cast by itself does not yet physically violate anything (meaning: it does not attempt to modify constant data and does not cause undefined behavior). Yet, it does open the door to such violations by returning a non-const pointer to const data to the caller, i.e. violates the conceptual rules of const-correctness.

是的,为了实现这样的功能,必须从输入指针显式地抛弃constness。请注意,强制转换本身并未实际违反任何内容(意思是:它不会尝试修改常量数据,也不会导致未定义的行为)。然而,它确实通过向const调用者返回一个非const指针来打开这种违规行为的大门,即违反了const-correctness的概念规则。

An alternative solution would be to provide two versions of the same standard function - a const one and a non-const one - but without C++-style function overloading this would require two distinctive function names, which does not necessarily look like a very good idea (and even with C++-style function overloading it has its issues too).

另一种解决方案是提供相同标准函数的两个版本 - 一个const和一个非const - 但没有C ++ - 样式函数重载这将需要两个独特的函数名称,这看起来不一定是一个非常好的主意(即使使用C ++风格的函数重载它也有它的问题)。

In this case it is effectively the responsibility of the caller to receive the result into a pointer of the same type as the one that was passed in as an argument. If the argument pointer was const-qualified, it is a very good programming practice to receive the result into a pointer that is const-qualified as well. As long as this guideline is observed, this idiom actually feels right at home in the realm of C language.

在这种情况下,调用者实际上有责任将结果接收到与作为参数传入的指针类型相同的指针中。如果参数指针是const限定的,那么将结果接收到const限定的指针是一种非常好的编程习惯。只要遵守这个指导原则,这个习惯用法在C语言领域实际上就像在家一样。