C/C++ static string in old package - c++

I have an old C/C++ package which I am trying to compile with CygWin because it needs Motif and other X- things. Most of it compiles OK but there are some warnings due to lines like....
static String fallbackResources[] = { "Joe", ..etc.. , NULL};
I get the compiler warning: deprecated conversion from string constant to ‘String {aka char*}’
I have googled and found many suggestions to avoid this warning by changing occurrences of say "char* fred[]" to "const char* fred[]" which I have done for most of the c++ files in the package and this has worked perfectly to remove the compiler warnings.
However I am stuck with the "static String" lines since when I change them by inserting "const" before "String" it makes no difference and if I change the "String" to "const char*" the warning disappears but the program doesn't compile due to an error later on where it sends the array to another function....
cannot convert ‘const char*’ to ‘char**’ for argument ‘7’ to....
Any help would be very much appreciated.

Thanks all, googled more and found (https://stackoverflow.com/a/14648630/3100869) - the answer seems to be to use const_cast's like this:
static String fallbackResources[] = { const_cast("Joe"), ..etc.. , NULL};
... and the warnings go away!

The problem is that you've got two levels of const on pointers: the pointer itself and what it points to. char const * is a pointer to const char (read from right to left), whereas char* const is a const pointer to char.
It seems that String in your case is a typedef for char*. Making that const like you did turns it into a char* const. You need to fix the typedef.

Related

How do I create an array of pointers in c++

I'm trying to create an array of pointers using my professors example in class. I can't seem to get it to work though.
char * ISBN[] = {
"1-214-02031-3",
"0-070-21604-5",
"2-14-241242-4",
"2-120-12311-x",
"0-534-95207-x",
"2-034-00312-2",
"1-013-10201-2",
"2-142-1223",
"3-001-0000a-4",
};
This is my professors example of declaring an array of pointers of type char. He says this is what we should do for the assignment. Sadly, I'm getting the error -
Error (active) E0144 a value of type "const char *" cannot be used to initialize an entity of type "char *" -
I've asked about this before and someone said that char * has been deprecated. But the professor says that this is the declaration that we should use for the assignment. How would I go about trying to figure out how to get this array working? What exactly is this declaration doing?
const char * ISBN[] = {
"1-214-02031-3",
"0-070-21604-5",
"2-14-241242-4",
"2-120-12311-x",
"0-534-95207-x",
"2-034-00312-2",
"1-013-10201-2",
"2-142-1223",
"3-001-0000a-4",
};
I guess I just needed to add const in front of char *. I still got much to learn. Thanks everyone.
It is simply because you are trying to assign string literals to char pointer.In c++ string literals are const char pointer because as string literals are stored in read-only memory.Another reason is for optimisation for compilers(storing only one instance of a literal that is repeated many times in the source). So you get multiple pointers to the same memory, instead of each occupying a separate chunk of memory.

How to resolve a "cppcoreguidelines-pro-type-cstyle-cast" error in C++?

I'm working on C++ with Visual Studio 2015 64-bit and Clang as my compiler.
I tried to convert a string to unsigned char* with the code below:
string content = "some content from file";
unsigned char* m_Test = (unsigned char*)content.c_str();
However, this resulted in an error when I tried to build the project:
error: do not use C-style cast to convert between unrelated types
[cppcoreguidelines-pro-type-cstyle-cast,-warnings-as-errors]
Any idea how I can work around it? Really appreciate it if you can shed some light.
You have two (or 3) options:
1) Replace the C-style cast with the appropriate C++ cast (static_cast, const_cast, reinterpret_cast or dynamic_cast).
2) (better option) Find a way to write your code where a cast is not needed in the first place.
3) Ignore/suppress the warning (not what I would recommend, though it is an option).
In modern C++ the standard cstyle casts should not be used, because they are error prone. To be able to cast from const char * returned by .c_str() method of the string. You need to be tough on compiler. So much so, that reinterpret_cast is needed. Even then you need to preserve the constness. That can be casted away as well. So the code would look like this:
string content = "some content from file";
const unsigned char* m_Test = reinterpret_cast<const unsigned char*>(content.c_str());
The reinterpret_cast just tells the compiler "From now on, treat this data as stated."
You can use the C++ cast way with static_cast:
EDIT: As pointed out in the comments, you also need a const_cast for your particular case:
string content = "some content from file";
unsigned char* m_Test = static_cast<unsigned char*>(const_cast<char*>(content.c_str()));

strcpy on a string pointer gives errors

I have read a lot about the subject and I am confused .
What used to work in a C file ,not working on a cpp file :
char *builtinFunctions[20];
Then I get error on the strcpy function here :
void Intepreter::setBuiltIns(char *builtins)
{
strcpy(builtinFunctions, builtins); // no matching function call to strcpy
}
I probably don't understand the basics here, but why in C++ this will not work ( do i need to use = instead ? )
strcpy(char *, const char*) = thats the structure
if I change the builtinFunctions from being a pointer it works.
EDIT:
The reason for being a const before this edit is that I read here :
Why is conversion from string constant to 'char*' valid in C but invalid in C++
that char *builtinFunctions[20]; will produce warning when :
builtinFunctions[0]="me";
and it did. I could fix it by removing the const .
This is an array of pointers to char.
char *builtinFunctions[20];
So you call
strcpy(builtinFunctions, builtins);
gets treated as strcpy(char **, char*), not as strcpy(char *dest, const char *src). So you get a mismatch for first parameter type.
EDIT:
So let's suppose builtinFunctions is "an array of words" you wish to populate, with void Intepreter::setBuiltIns(char *builtins) meant to do just that with it's first parameter being a pointer to a new incoming word. (And you're doing this in a C-style manner. Well, up to you.)
Some things to consider.
If you declare an array type arrName[N]; then the array's name
being used all alone without index is treated as a variable of type
type *arrName. If you type is initially char *, then
builtinFunctions by itself is of type char**. That's why your
strcpy fails, but strcpy(builtinFunctions[someIndex], builtins);
works.
Before invoking strcpy you should consider, if you have a
destination space allocated. builtinFunctions[someIndex] is of
type char *. Where does it point to? Is it a valid pointer to an
allocated space, or a gateway to hell of undefined behaviour strcpy will happily take you to?

cannot convert from 'const char [3]' to 'char *' x100000 (Qt Creator C++ Windows 32)

Everything was working fine just five minutes ago when I tapped f5 and got 102 errors:
error: C2440: 'initializing' : cannot convert from 'const char [17]' to 'char *'
Conversion from string literal loses const qualifier (see /Zc:strictStrings)
That specific one is at line 30:
char* hexchars = "0123456789ABCDEF";
I haven't touched the file the errors are in for at least a week. I'd normally say I accidentally changed something in the compile args or something, but I haven't opened settings since much before it started erroring.
Any ideas? I must have absentmindedly changed some setting but I really can't remember thinking "uh oh what did I just do?"
When you use code like this
char *astring2 = "some letters";
C++ (and C) puts that into read only memory. You can not modify the contents of a char pointer initialized with a literal even if it is not const.
Also you can not change the address of the pointer because it will cause a memory leak due to the rule above.
This, however, does not follow that rule UNLESS you make it const:
char astring[] = "some letters that can be changed";
char *ptrToString = astring; //work
astring2 = astring //not work
String literals are of type char const[N] since C++ was first standardized. At this point C didn't support const and a lot of code assigned string literals to char*. As a result a special rule was present in C++ which allowed initialization of char* from string literals. This rule was immediately deprecated.
C99 introduced a const keyword, too. When C++11 was standardized the deprecated rules was pulled and it is no illegal to initialize a char* from a string literal as it should have been right from the stand. The expectation was that C++ compilers warned about the deprecated assignment since years (and all vendors stated they did), i.e., users had years of lead-time to fix their code.
The obvious fix is to initialize a char const* instead of a char* from a string literal.
If you really need a pointer to a mutable array of chars you can create it and get it initialized using
char array[] = "string literal";

How to initialize char* args[] without getting a compiler warning

Compiler is complaining on the following line.
char* args[] = {"/bin/bla.py", "-h"};
The error is:
deprecated conversion from string constant to 'char*'
I am compiling with -Werror=write-strings so I know how to stop getting this error;
but I am looking to see what am I doing wrong and how I can prevent the warning?
Thanks,
Change to char const *args[]. If you do not intend to change which strings are in this table, then use
char const *const args[] = { ....
The write-strings error means to give an error for your code. Your code is legal but bad practice. It's bad practice because string literals contain const chars , so it would be undefined behaviour to write to them. Making the pointer point to const chars means you get a compiler message if you try to write to them.