error: invalid conversion from 'const char*' to 'char*' [-fpermissive] - c++

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.

Related

A value of type "const char*" cannot be used to initialize an entity of type "char *"

I have a code like this but I keep receiving this error :
A value of type "const char*" cannot be used to initialize an entity of type "char *"
What is going on?
I have read up on the following threads but have not been able to see any result to my answer as all of them are either from char to char* or char* to char:
Value type const char cannot be used to initialize an entity of type char*
Value of type char* cannot be used to initialize an entity of type "char"
#include <iostream>;
using namespace std;
int main() {
int x = 0; //variable x created
int cars (14);//cars is created as a variable with value 14
int debt{ -1000 };//debt created with value 1000
float cash = 2.32;
double credit = 32.32;
char a = 'a';//for char you must use a single quote and not double
char* sandwich = "ham";
return 0;
}
I am using Visual Studio Community 2017
That is correct. Let’s say you had the following code:
const char hello[] = "hello, world!";
char* jello = hello; // Not allowed, because:
jello[0] = 'J'; // Undefined behavior!
Whoops! A const char* is a non-const pointer to const char. If you assign its value to a non-const char*, you’ve lost its const property.
A const pointer to non-const char would be a char* const, and you can initialize a char* from that all day if you want.
You can, if you really want, achieve this with const_cast<char*>(p), and I occasionally have, but it’s usually a sign of a serious design flaw. If you actually get the compiler to emit instructions to write to the memory aliased by a string constant, you get undefined behavior. One of the many things that might go wrong is that some implementations will store the constant in read-only memory and crash. Or the same bytes of memory might be re-used for more than one purpose, because after all, we warned you never to change it.
By the way, the rules in C are different. This is solely for backward-compatibility with early versions of C that did not have the const keyword, and you should never write new code that uses a non-const alias to a string constant.
You need to make your string literal type const because in C++ it is a constant array of char, unlike C where it is just an array of char. You cannot change a string literal, so making it const is preferred in C++ for extra safety. It is the same reason you have to use an explicit cast when going from const char* to char*. It's still technically "allowed" in C++ since it is allowed in C, which is why it's just a warning. It's still bad practice to do so. To fix the warning, make it const.
const char* sandwich = "ham";
Your code (and underlying assumption) is valid pre C++11 standard.
String literals (e.g. "ham") since C++11 are of type const char* (or const char[]) if you will instead of char * they used to be. [Always read specs for breaking changes!!!]
Hence the warning in VS 2017. Change the compiler version to pre C++11 version and you will be amazed.
This has subtle nuances and can cause frustrating debug sessions
// C++11 or later
auto c = "Rowdie";
// c has type const char*, can't use c to modify literal
c[0] = 'H'; // illegal - CTE
// -vs-
char * d = "Rowdie";
d[0] = 'H';
cout << d; // outputs "Howdie"
Also another example is auto return type from functions
auto get_literal() {
// ... function code
return "String Literal";
}
// and using value later
char* lit = get_literal(); // You get same error as const char* cannot be init to char*

strcpy() causes invalid conversion from ‘const char*’ to ‘char*’ [-fpermissive]

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;

Swapping two pointers to char in c++ by real call by reference

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().

Store c_str() as char *

I'm trying to use the function with the following declaration:
extern int stem(struct stemmer * z, char * b, int k)1
I'm trying to pass a C++ string to it, so I thought I'd use the c_str() function. It returns const char *. When I try to pass it to the stem() function, I get this error: error: invalid conversion from 'const char*' to 'char*' [-fpermissive].
How can I store the result of c_str() such that I can use it with the stem function?
Here is the code I'm running:
struct stemmer * z = create_stemmer();
char * b = s.c_str();
int res = stem(z, b, s.length()); //this doesn't work
free_stemmer(z);
return s.substr(0,res);
The problem you are having is that c_str() returns a buffer that can not be modified (const), while stem() may modify the buffer you pass in (not const). You should make a copy of the result of c_str() to get a modifiable buffer.
The page http://www.cplusplus.com/reference/string/string/c_str/ has more information on the C++ 98 and 11 versions. They suggest replacing char * b = s.c_str(); with the following:
char * b = new char [s.length()+1];
std::strcpy (b, s.c_str());
You shouldn't try to remove constness of a string returned by c_str():
char * b = s.c_str();
but you can pass an address of std::string's internal buffer directly:
int res = stem(z, static_cast<char*>(&s[0]), s.length());
If stem() is going to modify the string, then make a copy of it:
char * scpy= strdup( s.c_str()) ;
int res = stem(z, scpy, strlen( scpy));
free( scpy) ;
Use const_cast:
int res = stem(z, const_cast<char*>(s.c_str()), s.length()+1);
free_stemmer(z);
return s.substr(0,res);
Note the length+1 expression which might (or might not) be needed. C-style strings (char*) have an additional null terminator (zero byte, equivalent "\0") at the end. Your stem function may (or may not) expect a null terminator at the end of the string - try both variants.
Note also that "stem" function should not try to modify the string, otherwise bad things may happen (warning based on #David Heffernan's comment)
.c_str()
Just returns a pointer to the data, I would update the stem function to accept a 'const char*' unless you are wanting to modify the data in the string, in that case you should pass it as a new string object.
If you can't edit the stem function you can cast it:
int res = stem(z, const_cast<char*>(s.c_str()), s.length());
It's not good to do this, but nothing stops you:
#include <iostream>
#include <string>
using namespace std;
void foo(char *ch)
{
ch[0] = 'B';
}
int main()
{
string str = "helo world";
char *ch = const_cast<char *>(str.c_str());
foo(ch);
// Belo world
cout << str << endl;
return 0;
}

Assign new size to const char* using memset()

I have declare buffer const char* buf;
Later on I want to re assign size using memset
buffer_len = 1024;
memset(buf, '\0', buffer_len);
buf[strlen(buf)-1]='\0';
gives error:
client.cpp:73:30: error: invalid conversion from ‘const void*’ to ‘void*’ [-fpermissive]
In file included from client.cpp:2:0:
/usr/include/string.h:62:14: error: initializing argument 1 of ‘void* memset(void*, int, size_t)’ [-fpermissive]
client.cpp:75:21: error: assignment of read-only location ‘*(buf + (((sizetype)strlen(buf)) + -1u))’
I know it's due to const but is there any alternative or way to perform it event it is const?
The assignment buf[strlen(buf)-1]='\0'; is invalid because you defined buf as const: const char* buf; Read compiler's error message: error: assignment of read-only location.
One point: You set buf with nul \0 so length of buf is 0 (\0 at zero index) then if suppose you don't declare buf as const even then you would be assiging at negative index because strlen(buf) - 1 == 0 - 1 = -1 – Undefined behaviour
memset does not assign size. It fills a buffer with bytes. Filling a buffer declared as const char* makes no sense, since the reason you declare it const is for yourself not to write to it.
You could create a different array instead, since this const does not prevent you from changing the pointer itself.
Reassigning size should probably be called reallocating memory, you can use one of malloc, calloc or others to do it. Or since you've tagged this with c++, probably using the new operator would be the best idea.
Obvious the author is asking a solution for what he want to operate. And simply explanation of the comping error is satisfactory. I do not want to explain why the author's code is not compiling, cause the above answers explain very well about this.
I am try to give a solution if the author really want to do all the operations he meant in his code, though I do not recommend to do that in real world software project.
Use const_cast to remove the const property of the variable:
const char* buf;
...
buffer_len = 1024;
...
char *ptr = const_cast<char *>(buf);
memset(ptr, '\0', buffer_len);
ptr[strlen(buf)-1]='\0';
A way to achieve flexible strings in C is to use realloc:
//Get some malloc'ed strings.
char* myString = asprintf("my cool, malloc()-allocated string\n");
char* myOtherString = asprintf("Oh, and by the way: Hello World!\n");
//Make room in myString to append the other string.
size_t finalStringSize = strlen(myString) + strlen(myOtherString);
myString = realloc(myString, finalStringSize + 1); //+1 for termination
//Concatenate the strings
strcat(myString, myOtherString);
free(myOtherString), myOtherString = NULL;
But, of course, using C++ std::strings should be less of a hassle.