Consider:
| char mystring[255];
char *a = mystring;
|
This defines an array of 255 bytes (if char is an unsigned byte on your system) as "mystring" and assigns char *a to point to mystring[0] (first character in string).
Now consider the Pre-processor Macro of __FILE__, which is from "C and C++"
__FILE__ expands into a string literal, just as if you had written "/path/to/current/file.cpp"
A string literal is an unmodifiable "lvalue" -- in other words it is implicitly constant to write:
"this string"
This makes a lot of sense. There is no way at run-time a program should be able to modify the source code files, and since this was defined in the source code files and not in a way that makes sense to be modifiable, it is read only protected and therefore technically a "const char *" pointer to an unwrite-able block of memory (program constants) (This is quite well explained by this article on Stack Overflow:
)
When you cast a const char * to a char *, this makes absolutely no sense. You are saying that your variable, let's call it foo, wants to allow writing to an un-write-able constant value, which is of the same type, but is allowed to be written.
Case in point:
| const char *myconst = "this value";
char *foo = (char *) myconst;
|
You get away with this as long as you respect that the value cannot be written in your program's execution. Trying to modify the value of foo[0] ('t') would result in a segmentation fault.
The reason why VS2017 complains about this is because for the first time really in the history of Microsoft's Visual Studio, it complies most closely with ISO standards, which define C2440 as a blocking error, rather than a warning or being completely ignore-able as it may have in the past:
https://msdn.microsoft.com/en-us/library/dn449508.aspx (2013, 2015)
https://docs.microsoft.com/en-us/...ler-errors-1/compiler-error-c2440 (2017)
(There's also the compiler settings "Conformance Mode" and "C++ Language Standard", etc you might find while searching for this issue)
You might think you can turn it off by using the compiler option like this article states:
https://docs.microsoft.com/en-us/...le-string-literal-type-conversion (2017)
But, it doesn't seem to work for me, for perhaps a reason that is unique to my project properties (I have no idea). (I tried this with a default project for a Windows Console Application.)
My solution is to make a copy, or to simply use the proper "const char *" type.
1
2
3
4
5
6
7
8
9
10
11
12
13
14 | // Example 1:
#include <string>
using namespace std;
string mine=string(__FILE__);
// Example 2:
const char *filename=__FILE__;
string user_entered_filename = whatever;
filename = user_entered_filename.c_str();
...
|
Both involve using std::string, one of the few STL objects I use. Of course, you wouldn't want to do this if you were going to write a DLL, in that case you'd need to write your own converter.
You can easily write your own string class, and use that instead of std::string, converting both char * and const char * to a common "string" that has a .c_str() equivalent method function, but all of this requires use of C++, not "pure C" -- you could write a function in C to do the conversion for you, too, using a static or global string warehouse.
You could also experiment with writing your own const_cast