简体   繁体   中英

How strstr return is not a constant

The standard function strstr is used to find the location of a sub-string in a string. Both the arguments of the function are of const char * type, but the return type is char * .

I would like to know how a standard function is implemented violating the const-correctness.

All the const char * is telling you is that strstr is not going to modify the string you pass into it.

Whether you modify the returned string or not is up to you as it is your string!

In C++ this has been changed by overloading the method and having two versions, the const input version has a const output.

In C it doesn't have quite that level of safety built in for you and assumes you know yourself whether you should be modifying the returned string.

According to ISO C++ 21.8(7) strstr returns a const char* or a char* depending on if it gets a const char* or a char* .

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

C allows pointing to memory with const or non-const pointers, regardless if the object was defined with the const qualifier or not.

6.5 Expressions

  1. An object shall have its stored value accessed only by an lvalue expression that has one of the following types:

— a qualified version of a type compatible with the effective type of the object,

The prototype of strstr in C is:

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

The returned pointer, if valid, points to string s1. This can be achieved with a cast:

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

The problem is modifying that memory.

6.7.3 Type qualifiers

  1. If an attempt is made to modify an object defined with a const-qualified type through use of an lvalue with non-const-qualified type, the behavior is undefined.

Since you created the string, you should know whether you can modify it or not, therefore you can accept the return value with a pointer to const, to avoid any problems:

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

It's done by specifying the signature, and leaving the implementation up to the compiler builders.

Note that returning a char* which points to a const char[] string is just dangerous, but not yet a violation of any rule. However, any attempt to write to that memory is still Undefined Behavior.

The strstr function dates back to an era before there was such a thing as a const pointer. In cases were it would be legal for code to write to memory identified by the first pointer passed to strstr , it would be legal for code to write to memory identified by the returned pointer, and in cases where the returned value would only be used in ways that were legal with a pointer to read-only memory (eg a string literal), one could legally pass such a pointer to strstr .

If a functionality similar to strstr were being defined today, it might be implemented using two methods--one of which could accept any pointer and return a pointer which could not be written by the recipient, and one of which would only accept writable pointers but would return a pointer that the recipient could use as it saw fit. Because some code which used strstr would need to pass read-only pointers, however, and because some code which used strstr needed to be able to write to the pointers that it would yield when given writable pointers, it was necessary to have one set of pointer qualifications work both ways. The consequence is a set of pointer qualifications which are not really "safe" [since it may return a writable pointer to a read-only area of memory] and which will let code compile in some cases where it really "shouldn't", but which will allow code written before the days of const pointers to continue working as intended.

C++ provides two versions one that takes const arguments and ones that takes non-const.

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

Since in C we can not overload, we are left with two unpleasant choices:

  • Either we take the arguments as non-const but if our sources are indeed const then we need to perform an unpleasant cast to non-const.
  • The second option is the one we have which is that we take the arguments as const but we return a non-const. We could return a const char* but then we could never modify the result.

The return value is not the variable that you have passed to the function as parameter. This function returns a pointer to the first occurrence in haystack of any of the entire sequence of characters specified in needle, or a null pointer if the sequence is not present in haystack.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM