Reputation: 54591
The function char* strrchr(const char *str, int ch)
returns a pointer (char*
) within str
(const char *
) where the last occurrence of ch
is located.
So we can write the following code without any cast:
#include <string.h>
int main()
{
const char CONSTSTR[] = "foo/bar/foobar.txt";
char *ptr = strrchr (CONSTSTR, '/');
*ptr++ = 'B';
*ptr++ = 'A';
*ptr++ = 'D';
}
What is the advantage to return char*
instead of const char*
?
EDIT:
As a Shafik Yaghmour pointed out, there are very good answers to How does strchr implementation work?
As my code is in C++, I will use <cstring>
instead of <string.h>
. Thanks for your answers ;-)
However, the Mike Seymour's answer fits best the question. I have even added a more detailed answer below to clearly say as strrchr()
is a C function (overload not permitted), the declaration fits both const and non-const strings. Because strrchr()
can be called with a non-const string, the returned string should also be non-const.
Upvotes: 7
Views: 3390
Reputation: 54591
strrchr()
from <string.h>
is a C function. As C does not permit function overloading, strrchr()
has been designed to fit both const and non-const strings.
char* strrchr( const char *str, int ch );
strrchr()
may be called with a non-const string, and therefore the returned string should also be non-const as explained in the following examples.
const context without compilation error:
#include <string.h>
int main()
{
const char CONSTSTR[] = "foo/bar/foobar.txt";
const char *basename = strrchr (CONSTSTR, '/');
// basename points to "foobar.txt"
}
non-const context without compilation error:
#include <string.h>
int main()
{
char nonconst[] = "foo/bar/foobar.txt";
char *basename = strrchr (nonconst, '/');
basename[0] = 'G';
basename[3] = 'D';
// basename points to "GooDar.txt"
}
Bad usage also without compilation error:
#include <string.h>
int main()
{
const char CONSTSTR[] = "foo/bar/foobar.txt";
char *nonconst = strrchr (CONSTSTR, '/');
*nonconst++ = 'B';
*nonconst++ = 'A'; // drawback of the unique declaration:
*nonconst++ = 'D'; // no compilation error
}
const char* strrchr( const char* str, int ch ); //1st
char* strrchr( char* str, int ch ); //2nd
const context uses the 1st one:
#include <cstring>
int main()
{
const char CONSTSTR[] = "foo/bar/foobar.txt";
const char *basename = std::strrchr (CONSTSTR, '/');
// basename points to "foobar.txt"
}
non-const context uses the 2nd one:
#include <cstring>
int main()
{
char nonconst[] = "foo/bar/foobar.txt";
char *basename = std::strrchr (nonconst, '/');
basename[0] = 'G';
basename[3] = 'D';
// basename points to "GooDar.txt"
}
Bad usage should produce compilation error:
#include <cstring>
int main()
{
const char CONSTSTR[] = "foo/bar/foobar.txt";
char *nonconst = std::strrchr (CONSTSTR, '/');
// Visual C++ v10 (2010)
// error C2440: 'initializing' : cannot convert from 'const char *' to 'char *'
*nonconst++ = 'B';
*nonconst++ = 'A';
*nonconst++ = 'D';
}
But this last example does not produce any compilation error using g++ -Wall file.cpp
. Tested using GCC versions 4.1.2 (RedHat) and 4.7.2 (MinGW).
Upvotes: 2
Reputation: 272607
You're looking at the legacy function from the C standard library (<string.h>
). The C++ library (<cstring>
) introduces appropriate const
and non-const
overloads, so you should use that wherever possible.
Upvotes: 13
Reputation: 254561
In C, the function must either be like this, or force the user to use dodgy casts in many situations:
const
pointer, you couldn't search a const
string;const
pointer, you couldn't use it to modify a non-const
string.In C++, you should include <cstring>
rather than the deprecated C-only header. That will give you two const-correct overloads, which couldn't be done in C:
const char* strchr(const char* s, int c);
char* strchr( char* s, int c);
Upvotes: 7
Reputation: 133599
Why would you forbid the code from modifying a returned variable? Mind that const char *
is not char * const
, you would be allowed to modify the character in any case, but you won't have control on the returned value itself, which doesn't make much sense since you could want to change it and edit the underlying string in a different position for your purpose.
Upvotes: 0
Reputation: 9599
const char *str
means strrchr
guarantees not to modify str
.
Returning const char *
means strrchr
forbids you to modify the returned value.
Upvotes: 3