Question

While adding a detailed answer, I noticed that GCC does not warn the following code while Visual C++ complains.

#include <cstring>
int main()
{
    const char CONSTSTR[] = "foo/bar/foobar.txt";

    char *nonconst = std::strrchr (CONSTSTR, '/');
    // cannot convert from 'const char *' to 'char *'

    *nonconst++ = 'B';
    *nonconst++ = 'A';
    *nonconst++ = 'D';
}

I have tested three different GCC versions:

  • 4.1.2 on Red Hat (Linux)
  • 4.5.3 on Cygwin (Windows)
  • 4.7.2 on MinGW (Windows)

But all these three GCC versions compiled this code without any warning/error:

> g++ -Wall -Wextra -pedantic -ansi test.cpp && echo "success"
success

While Microsoft compiler v16 complains:

> cl -c test.cpp
Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 16.00.30319.01 for 80x86
Copyright (C) Microsoft Corporation.  All rights reserved.

test.cpp
test.cpp(5) : error C2440: 'initializing' : cannot convert from 'const char *' to 'char *'
        Conversion loses qualifiers

(from my office, I do not have access to ideone/codepad/... to test it using other versions)

As this code uses std::strrchr, I do not understand why GCC does not complain.

const char* strrchr( const char* str, int ch );  //the code above uses this declaration
      char* strrchr(       char* str, int ch );

My question: Why does g++ successfully compile this code without any warning/error? Is it a bug? a feature? a miss-configuration on my side?

Était-ce utile?

La solution

Actually your g++ does not accept the conversion from 'const char *' to 'char *', it's just that on your version std::strrchr() returns a char* (incorrectly, instead of a const char*).

To verify the first part of my statement, try to compile the following on your GCC versions, I predict that all will correctly issue an error:

int main()
{
    const char* p = "foo";
    char* q = p;  // error, invalid conversion from 'const char*' to 'char*'
}

Now for the second part, I tried to compile the following minimal code, whose actual aim is to trigger an error in order to list the declared overloads of std::strrchr:

#include <cstring>
void (*p)() = &std::strrchr;  // error here, with "candidates are: ..."
int main() {}

Well, with gcc 4.7.2 the message shows the expected "all non-const" and "all const" overloads:

prog.cpp:2:21: error: no matches converting function ‘strrchr’ to type ‘void (*)()’
In file included from /usr/include/c++/4.7/cstring:44:0,
                 from prog.cpp:1:
/usr/include/string.h:249:1: error: candidates are: char* strrchr(char*, int)
/usr/include/string.h:255:1: error:                 const char* strrchr(const char*, int)

i.e. the prototypes

      char* strrchr(       char* , int );
const char* strrchr( const char* , int );  // Question's code will use this one (-> error)

But with gcc 4.3.2 the message was different:

prog.cpp:2: error: no matches converting function 'strrchr' to type 'void (*)()'
/usr/include/string.h:171: error: candidates are: char* strrchr(const char*, int)
/usr/include/c++/4.3/cstring:118: error:                 char* std::strrchr(char*, int)

i.e. the overloads were

      char* strrchr( const char* , int );  // Question's code would use this one (-> no error...)
      char* strrchr(       char* , int );

(the second one is the C++ non-const overload; but the first one is the old C version, and should instead be the C++ const overload).

This it seems that the headers (<cstring> and/or <string.h>) were incorrect on this version, and I suspect that it's the same on yours.


Edit: I found for example a discussion, a blog post and a bug report (for strchr not strrchr but it's the same story).

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top