I'm trying to have an object named PReader (with a function named Execute(), taking no arguments) have a filename passed in through the constructor so Execute() can access it. The way I'm trying to set it up involves having the constructor allocate the memory for a string, then copy it over, and setting up a destructor for it. I know it's awkward, but I know this setup will make future additions to my project easier.
Here's how my object is currently set up:
#include <PReader.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
PReader::PReader(const char *f)
{
filename = new char[strlen(f)+1];
strcpy(filename, f);
}
PReader::~PReader()
{
delete [] filename;
}
void PReader::Execute(void)
{
FILE *f = fopen(this->filename, "rb");
...
}
This is giving me the error:
PReader.C: In constructor ‘PReader::PReader(char*)’:
PReader.C:10:20: error: invalid conversion from ‘const char*’ to ‘char*’ [-fpermissive]
strcpy(filename, f);
^
In file included from /usr/include/stdlib.h:11:0,
from PReader.C:2:
/usr/include/string.h:30:8: error: initializing argument 1 of ‘char* strcpy(char*, const char*)’ [-fpermissive]
char *_EXFUN(strcpy,(char *__restrict, const char *__restrict));
For so few lines of code, I'm kind of surprised I'm missing something here. What can I do to ensure that conversion succeeds how I want it?
EDIT: PReader.h:
#include "source.h"
#ifndef PREADER_H
#define PREADER_H
class PReader : public Source
{
public:
const char* filename;
PReader(const char *filename);
virtual ~PReader();
virtual void Execute();
};
#endif
It looks like you defined filename to be a const char*. Make it a char* instead, so you can actually modify it (using strcpy) :
char* filename;
Or better yet, since this is C++, why not make use of std::string ?
There is a difference between these two declarations
const char * filename;
and
char * const filename;
The first one declares a pointer to a constant object of type const char. The pointer itself can be changed for example as ++filename but the object that pointed by the pointer may not be changed as for example ++*filename. So you may not use such a pointer in function std::strcpy as the first argument.
The second one declares a constant pointer to a non-constant object. So the pointer itself may not be changed. For example the compiler will issue an error for expression ++filename. But you may change the object pointed to by the pointer. For example ++*filename; Such a pointer you may use as the first argument in function std::strcpy.
And at last you can define non-constant pointer that points to a non-constant object
char * filename;
In this case you can change the pointer itself and change the object pointed by the pointer.
So in your class ypu should define filename either as
char * const filename;
or as
char * filename;
Take into account that pointers can be defined as
const char * const filename = "String Literal";
that is this statement defines a constant pointer to a constant object. You may change neither the pointer itself nor the object pointed by the pointer.
The equivalent declaration is
const char * constexpr filename = "String Literal";
In your header, you have
const char* filename;
and you are trying to strcpy into it. This is not allowed. Change that to
char* filename;
Related
The assignment C=R.c_str(); in the code below causes G++ to throw the following error:
error: invalid conversion from 'const char*' to 'char*' [-fpermissive]"
#include <iostream>
#include <string>
using namespace std;
int main()
{
string R = "killme";
char *C = new char[100];
C=R.c_str();
cout<<*C;
}
Why is this an error and how can I solve it?
The code has two problems. The main one, which causes a compile issue, is the assignment of c_str() result, which is const, to variable C, which is not const. The compiler tags this as an error, because otherwise you could do this:
C=R.c_str();
C[2] = 'c';
which would write to a read-only area in memory, causing undefined behavior.
You can fix it in two ways:
Declare C a const, i.e. const char *C = ..., or
Copy the content into space that you have allocated.
The first approach is simple - you do this:
const char *C = R.c_str();
The second approach works like this:
char *C = new char[R.size()+1];
std::strcpy(C, R.c_str());
The second problem is a memory leak: your code assigns C a result of new, but never deletes it. If you use strcpy approach, you need to add
delete[] C;
at the end of your program, once you are done using variable C.
I had the same kind of problem. See if it works:
string R= "killme";
char * cstr = new char [R.length()+1];
strcpy (cstr, R.c_str());
You have to include two libraries for this:
#include<string.h>
#include<cstring>
string::c_str() returns a const char* not a char*. This is the reason of the error.
For more information of the std::string::c_str() see the link: http://www.cplusplus.com/reference/string/string/c_str/
Yes, both the points mentioned above are also correct.
I am trying to swap two points on const char with real call-by-reference. But I have problems.
void swap(const char *&str1, const char *&str2) { //swap char pointers
const char *one = str1;
str1 = str2;
str2 = one;
}
int main(void){
const char *str1 = "Apple";
const char *str2 = "Potato";
swap(*str1, *str2);
return 0.0;
}
I keep on getting this error:
invalid conversion from 'char' to 'const char'
You shouldn't be dereferences the pointers when calling swap. You need to call:
swap(str1, str2);
Or, better still, use std::swap.
Also, if you're trying to run the code you've written they you'll need to either prototype swap or swap the functions around:
void swap(const char *&str1, const char *&str2)
{
const char *one = str1;
str1 = str2;
str2 = one;
}
int main(void)
{
const char *str1 = "Apple";
const char *str2 = "Potato";
swap(str1, str2);
return 0;
}
Also, main returns an int, not a float
You should use std::swap (located in either the <algorithm> or <utility> header) instead of rolling your own:
std::swap(str1, str2);
Also, you should consider using std::string instead of const char* in general:
std::string str1 = "Apple";
std::string str2 = "Potato";
of course the std::swap algorithm will still work just fine.
And finally, neither void in the argument list of main nor return 0.0 are necessary in C++.
Here's the code revisited with the advices above:
#include <algorithm>
#include <string>
#include <iostream>
int main() {
std::string str1 = "Apple";
std::string str2 = "Potato";
std::swap(str1, str2);
}
and here's the live example.
In response to Mr. Cthulhu down here, I'll try to answer the question more explicitly.
Your error is caused by the fact that by dereferencing the pointers of type const char* you are actually getting an expression of type const char& which is obviously incompatible with the type expressed in your swap function. Here's the correct call to the function:
swap(str1, str2);
But the again, why replicating the code of std::swap? (this is a rhetorical question, in case you were wondering wether to flag this as "not an answer")
You're defining swap() after you're calling it. In C++, functions should be defined before they are called. Move the definition of swap() to the top of the file, above main(). You will then get this error:
test.cpp:11: warning: converting to ‘int’ from ‘double’
Your main() function should return 0 (an int), not 0.0 which is a double.
Fixing this, you'll finally get this error:
test.cpp: In function ‘int main()’:
test.cpp:10: error: invalid initialization of reference of type ‘const char*&’ from expression of type ‘const char’
test.cpp:1: error: in passing argument 1 of ‘void swap(const char*&, const char*&)’
This is because you're dereferencing your arguments to swap(). Remove the * and the program now works fine.
However, you should simply remove your swap() function altogether, #include <utility>, and use std::swap().
What is the difference between the line that does not compile and the line that does compile?
The line that does not compile gives this warning: deprecated conversion from string constant to 'char*'
Also, I'm aware casting (char *) on the string being passed in to the function would solve the problem, but I would like to understand why that's even necessary when the 2nd line compiles just fine.
class Student {
public:
Student( char name[] ) {
}
}
int main() {
Student stud( "Kacy" ); //does not compile
char name[20] = "Kacy"; //compiles just fine
}
The char[] signature in the parameter is exactly the same as char*. In C++, it is illegal to convert a string constant char const* (the string "Kacy") to a char* because strings are immutable.
Your second example compiles because the name is an actual array. There is no change to char*.
As a solution, change your parameter to take a const string array:
Student(char const name[]);
which again is the same as
String(char const *name);
though you're better off using std::string:
#include <string>
class String
{
public:
String(std::string name);
};
C++ string literals have type "array of n const char", which decays into const char * in your use case. The implicit conversion to char * (that is, discarding the const) you're trying is deprecated, so there's a warning. Change the type in the constructor's signature or make an explicit const-cast.
From the C++ standard:
An ordinary string literal has type "array of n const char" and static storage duration
The string
"Kacy"
is not an array of characters when the compiler produces the code. Instead, it will stash the string "Kacy" somewhere in memory, and produce a pointer to that place. So what you get is a const char * pointing at the string "Kacy\0".
If you change your constructor to:
Student(const char *nmae)
you can use it both as:
Student stud("Kacy");
and as this:
char name[20] = "Kacy";
Student stud2(name);
Note here that the compiler will generate code to FILL the array name with the characters in "Kacy", which is different from just usinv "Kacy" as an argument to the Student constructor.
This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
C++ deprecated conversion from string constant to ‘char*’
I am having following code, though i didn't copy full code because it is huge.
Following code is in template class, and i am getting warning as below. Because of warning in template i am not able to instantiate it and getting "instantiated from here" error.
warning: deprecated conversion from string constant to 'char*''
void ErrorMessageInRaphsodyCode(char* pcCompleteMessage, char* pcMessage, char* pcFileName, unsigned int RowNo)
{
//...
}
char cCompleteMessage[200];
memset(cCompleteMessage, 0x00, sizeof(cCompleteMessage));
char*cMessage = "add reorgenize failed";
ErrorMessageInRaphsodyCode(cCompleteMessage, cMessage, "omcollec.h", __LINE__);
My question is what is best way to get rid of above warning ?
If a function takes a char const *, it guarantees that it only reads whatever data the pointer points to. However, if it takes a non-const pointer, like char *, it might write to it.
As it is not legal to write to a string literal, the compiler will issue a warning.
The best solution is to change the function to accept char const * rather than char *.
char cMessage[] = "add reorganize failed";
This should get rid of the warning.
Best way to get rid of it is to fix the function that is taking the parameter.
If your code is correct and the function does indeed take string constants, it should say so in its prototype:
void ErrorMessageInRaphsodyCode(char* pcCompleteMessage, char* pcMessage, const char* pcFileName, unsigned int RowNo)
If you can't do that (you don't have the code), you can create an inline wrapper:
inline void ErrorMessageInRaphsodyCodeX(char* p1, char* p2, const char* p3, unsigned int p4)
{ ErrorMessageInRaphsodyCode(p1,p2,(char*)p3,p4); }
and use the wrapper instead.
If your code is incorrect and the function does actually require writeable memory (which I highly doubt), you will need to make the string writeable by either creating a local array as Jan suggested, or mallocating enough memory.
(1) Make the variable a const char*
(..., const char* pcFileName, ...)
(2) If above is not possible and you want to retain the state of char* and const char* then make the function a template:
template<typename CHAR_TYPE> // <--- accepts 'char*' or 'const char*'
void ErrorMessageInRaphsodyCode(char* pcCompleteMessage, CHAR_TYPE* pcMessage, char* pcFileName, unsigned int RowNo)
{
//...
}
function c_str() of std::string class.
I have a class with a private char str[256];
and for it I have an explicit constructor:
explicit myClass(char *func)
{
strcpy(str,func);
}
I call it as:
myClass obj("example");
When I compile this I get the following warning:
deprecated conversion from string constant to 'char*'
Why is this happening?
This is an error message you see whenever you have a situation like the following:
char* pointer_to_nonconst = "string literal";
Why? Well, C and C++ differ in the type of the string literal. In C the type is array of char and in C++ it is constant array of char. In any case, you are not allowed to change the characters of the string literal, so the const in C++ is not really a restriction but more of a type safety thing. A conversion from const char* to char* is generally not possible without an explicit cast for safety reasons. But for backwards compatibility with C the language C++ still allows assigning a string literal to a char* and gives you a warning about this conversion being deprecated.
So, somewhere you are missing one or more consts in your program for const correctness. But the code you showed to us is not the problem as it does not do this kind of deprecated conversion. The warning must have come from some other place.
The warning:
deprecated conversion from string constant to 'char*'
is given because you are doing somewhere (not in the code you posted) something like:
void foo(char* str);
foo("hello");
The problem is that you are trying to convert a string literal (with type const char[]) to char*.
You can convert a const char[] to const char* because the array decays to the pointer, but what you are doing is making a mutable a constant.
This conversion is probably allowed for C compatibility and just gives you the warning mentioned.
As answer no. 2 by fnieto - Fernando Nieto clearly and correctly describes that this warning is given because somewhere in your code you are doing (not in the code you posted) something like:
void foo(char* str);
foo("hello");
However, if you want to keep your code warning-free as well then just make respective change in your code:
void foo(char* str);
foo((char *)"hello");
That is, simply cast the string constant to (char *).
There are 3 solutions:
Solution 1:
const char *x = "foo bar";
Solution 2:
char *x = (char *)"foo bar";
Solution 3:
char* x = (char*) malloc(strlen("foo bar")+1); // +1 for the terminator
strcpy(x,"foo bar");
Arrays also can be used instead of pointers because an array is already a constant pointer.
Update: See the comments for security concerns regarding solution 3.
A reason for this problem (which is even harder to detect than the issue with char* str = "some string" - which others have explained) is when you are using constexpr.
constexpr char* str = "some string";
It seems that it would behave similar to const char* str, and so would not cause a warning, as it occurs before char*, but it instead behaves as char* const str.
Details
Constant pointer, and pointer to a constant. The difference between const char* str, and char* const str can be explained as follows.
const char* str : Declare str to be a pointer to a const char. This means that the data to which this pointer is pointing to it constant. The pointer can be modified, but any attempt to modify the data would throw a compilation error.
str++ ; : VALID. We are modifying the pointer, and not the data being pointed to.
*str = 'a'; : INVALID. We are trying to modify the data being pointed to.
char* const str : Declare str to be a const pointer to char. This means that point is now constant, but the data being pointed too is not. The pointer cannot be modified but we can modify the data using the pointer.
str++ ; : INVALID. We are trying to modify the pointer variable, which is a constant.
*str = 'a'; : VALID. We are trying to modify the data being pointed to. In our case this will not cause a compilation error, but will cause a runtime error, as the string will most probably will go into a read only section of the compiled binary. This statement would make sense if we had dynamically allocated memory, eg. char* const str = new char[5];.
const char* const str : Declare str to be a const pointer to a const char. In this case we can neither modify the pointer, nor the data being pointed to.
str++ ; : INVALID. We are trying to modify the pointer variable, which is a constant.
*str = 'a'; : INVALID. We are trying to modify the data pointed by this pointer, which is also constant.
In my case the issue was that I was expecting constexpr char* str to behave as const char* str, and not char* const str, since visually it seems closer to the former.
Also, the warning generated for constexpr char* str = "some string" is slightly different from char* str = "some string".
Compiler warning for constexpr char* str = "some string": ISO C++11 does not allow conversion from string literal to 'char *const'
Compiler warning for char* str = "some string": ISO C++11 does not allow conversion from string literal to 'char *'.
Tip
You can use C gibberish ↔ English converter to convert C declarations to easily understandable English statements, and vice versa. This is a C only tool, and thus wont support things (like constexpr) which are exclusive to C++.
In fact a string constant literal is neither a const char * nor a char* but a char[]. Its quite strange but written down in the c++ specifications; If you modify it the behavior is undefined because the compiler may store it in the code segment.
Maybe you can try this:
void foo(const char* str)
{
// Do something
}
foo("Hello")
It works for me
I solve this problem by adding this macro in the beginning of the code, somewhere. Or add it in <iostream>, hehe.
#define C_TEXT( text ) ((char*)std::string( text ).c_str())
I also got the same problem. And what I simple did is just adding const char* instead of char*. And the problem solved. As others have mentioned above it is a compatible error. C treats strings as char arrays while C++ treat them as const char arrays.
For what its worth, I find this simple wrapper class to be helpful for converting C++ strings to char *:
class StringWrapper {
std::vector<char> vec;
public:
StringWrapper(const std::string &str) : vec(str.begin(), str.end()) {
}
char *getChars() {
return &vec[0];
}
};
The following illustrates the solution, assign your string to a variable pointer to a constant array of char (a string is a constant pointer to a constant array of char - plus length info):
#include <iostream>
void Swap(const char * & left, const char * & right) {
const char *const temp = left;
left = right;
right = temp;
}
int main() {
const char * x = "Hello"; // These works because you are making a variable
const char * y = "World"; // pointer to a constant string
std::cout << "x = " << x << ", y = " << y << '\n';
Swap(x, y);
std::cout << "x = " << x << ", y = " << y << '\n';
}