Why my compiler(GCC) doesnt implicitly cast from char** to const char**?
Thie following code:
#include <iostream>
void print(const char** thing) {
std::cout << thing[0] << std::endl;
}
int main(int argc, char** argv) {
print(argv);
}
Gives the following error:
oi.cpp: In function ‘int main(int, char**)’:
oi.cpp:8:12: error: invalid conversion from ‘char**’ to ‘const char**’ [-fpermissive]
oi.cpp:3:6: error: initializing argument 1 of ‘void print(const char**)’ [-fpermissive]
Such a conversion would allow you to put a const char* into your array of char*, which would be unsafe. In print you could do:
thing[0] = "abc";
Now argv[0] would point to a string literal that cannot be modified, while main expects it to be non-const (char*). So for type safety this conversion is not allowed.
#Fred Overflow's link to the FAQ is a complete answer. But (sorry Marshall) it's not the most clear explanation. I don't know if mine is more clear, but I hope so.
The thing is, if p is a char* pointer, then it can be used to modify whatever it's pointing at.
And if you could obtain a pointer pp that points to p, but with pp of type char const**, then you could use pp to assign to p the address of a const char.
And with that, you could then use p to modify the const char. Or, you would think you could. But that const char could even be in read-only memory…
In code:
char const c = 'a';
char* p = 0;
char const** pp = &p; // Not allowed. :-)
*pp = &c; // p now points to c.
*p = 'b'; // Uh oh.
As a practical solution to your code that does not compile, …
#include <iostream>
void print(const char** thing) {
std::cout << thing[0] << std::endl;
}
int main(int argc, char** argv) {
print(argv); // Dang, doesn't compile!
}
just do …
#include <iostream>
void print( char const* const* thing )
{
std::cout << thing[0] << std::endl;
}
int main( int argc, char** argv )
{
print( argv ); // OK. :-)
}
Cheers & hth.,
Note, that although
void dosmth(const char** thing);
int main(int argc, char** argv) {
dosmth(argv);
is forbidden, you can and should do
void dosmth(const char* const* thing);
int main(int argc, char** argv) {
dosmth(argv);
Which is probably what you wanted anyway. The point here is that thing now refers to a const char* array which is itself immutable and which referenced values char are themselves immutable.
So, for a "look at it, but do not change it" scenario, const char* const* is the type to use.
Note: I used the more common (but in my opinion inferior) standard of trying to write the const modifier as left as possible. Personally, I recommend writing char const* const* instead of const char* const* as it is hugely more concise that way.
Because it might allow us to modify a constant value. Read here to understand why: http://c-faq.com/ansi/constmismatch.html
Related
As in the code below, I can't pass this parameter, how do I fix it?
E0167 The "const char *" type argument is incompatible with the "char *" type parameter
Code example:
#include <iostream>
using namespace std;
int PrintString(char* s)
{
cout << s << endl;
}
int main(int argc, char* argv[])
{
PrintString("TESTEEEE");
return 0;
}
I've already tried PrintString(L"TESTEEEE");
I've also tried setting the Project -> Properties -> General -> Character Set option to use Multi-Byte Character Set.
This literal "TESTEEEE" is of type char const[9]. When used as an argument to a function, it can decay to char const* but not to char*. Hence to use your function, you have to make the parameter fit to your argument or the opposite as follows
#include <iostream>
using namespace std;
int PrintString(const char* s)
{
cout << s << endl;
}
int main(int argc, char* argv[])
{
PrintString("TESTEEEE");
return 0;
}
live
OR
#include <iostream>
using namespace std;
int PrintString( char* s)
{
cout << s << endl;
}
int main(int argc, char* argv[])
{
char myArr[] = "TESTEEEE";
PrintString(myArr);
return 0;
}
live
You have incorrect constness, it should be:
void PrintString(const char* s)
I have a static method inside my class, which I use for a callback.
Inside this callback I want to add a value to result.
This seems not to be possible because of the recast(?).
Is there a way to access the member variable result and add values to it after recasting, or do I need to think of a different way?
MyClass.h
class MyClass
{
public:
vector<string> result;
static int c_CB(void *data, int argc, char **argv, char **azColName);
int Callback(int argc, char **argv, char **azColName);
void Do(string query);
}
MyClass.cpp
void MyClass:Do(string query)
{
sqlite3_exec(this->dbResource, query.c_str(), this->c_CB , NULL, &this->errorMsg);
}
int MyClass::c_CB(void *NotUsed, int argc, char **argv, char **azColName)
{
MyClass* bar = reinterpret_cast<MyClass*>(NotUsed);
// after reinterpret cast, it does not work
//bar->result.insert(bar->result.end(), "foo");
// function call works
return bar->Callback(argc, argv, azColName);
}
int MyClass::Callback(int argc, char **argv, char **azColName)
{
cout << "working" << endl;
}
main.cpp
int main()
{
MyClass* cl = new MyClass();
cl->Do("something");
}
The documentation states that the fourth argument to sqlite3_exec is passed as the first argument of the callback.
Currently you are passing NULL, which you then cast to a MyClass* and attempt access the object, which results in undefined behaviour.
Use this as the fourth argument in place of NULL.
It seems you are trying to access a non-static member function from a static member callback function c_CB.
You were able to call a member function Callback but nothing from the class is accessible, but if I'm correct, the compiler just interpreted Callback as a static function.
If you actually breakpoint inside this function, you can see that none of your member variables actually have a memory address. And the current class, this is null
I'm not sure if the cout << statement still works or if its causing the problem
This is a possible solution to your issue, although it may not be the best one.
class MyClass
{
public:
vector<string> result;
static int c_CB(void *data, int argc, char **argv, char **azColName);
int Callback(int argc, char **argv, char **azColName);
void Do(string query);
void MemberFunction()
{
cout << "working" << endl;
}
static MyClass* currentClass; //Add a static class pointer and assign your class address to it before firing the callback.
}
MyClass* MyClass::currentClass = NULL;
void MyClass:Do(string query)
{
sqlite3_exec(this->dbResource, query.c_str(), this->c_CB , NULL, &this->errorMsg);
}
int MyClass::c_CB(void *NotUsed, int argc, char **argv, char **azColName)
{
MyClass* bar = reinterpret_cast<MyClass*>(NotUsed);
// after reinterpret cast, it does not work
//bar->result.insert(bar->result.end(), "foo");
// function call works
return bar->Callback(argc, argv, azColName);
}
int MyClass::Callback(int argc, char **argv, char **azColName)
{
currentClass->MemberFunction();
}
int main()
{
MyClass* cl = new MyClass();
MyClass::currentClass = this;
cl->Do("something");
}
I want to read argv[1] as char* so this is what I do
using namespace std;
const char *myarg = NULL;
void Plots(char* file);
int main( int size_t argc, char* argv[] ) {
myarg = argv[1];
cout<<" this is a test "<<argv[1]<<endl;
Plots(argv);
}
void Plots(char* fileList){
cout<< argument passed correctly "<<endl;
}
}
However, when executing I get
Error: Function Plot() is not defined in current scope :0:
argv is a char *[], which for all practical purposes is char **.
You declared
void Plots(char * file);
The parameter to Plots() is a char *.
Plots(argv);
This attempts to pass a char ** to a function that takes char * as a parameter.
Additionally, although you declared
void Plots(char * file);
but then you went ahead and defined
void Plot(char* fileList)
Furthermore:
cout<< argument passed correctly "<<endl;
There's a quote missing here.
So, there's three different bugs here.
Is there a easy way to convert a const char* to a const char** in C++ (without the use of Boost)? I've tried to use &myConstCharP but that didn't work.
I can't see a problem here. The following code works fine for me:
int main(int argc, char **argv)
{
char c = 'a';
const char *myConstCharP = &c;
const char **p = &myConstCharP;
printf("Your original char is: %c",**p);
}
I want to convert unsigned const char * to char const * for passing into strcpy function
Please suggest some method
(const char *) my_signed_char
In C++ there are more idiomatic ways to cast this, but since you are using strcpy you are not programming idiomatic C++ it seems.
This works for me; is it what you had in mind?
#include <stdio.h>
#include <string.h>
int main(int argc, char ** argv)
{
const char foo[] = "foo";
unsigned const char * x = (unsigned const char *) foo;
char bar[20];
strcpy(bar, (const char *)x);
printf("bar=[%s]\n", bar);
return 0;
}
Note that if you are instead trying to pass the (unsigned const char *) pointer into strcpy's first argument, then you are probably trying to do something you shouldn't (and the compiler is right to flag it as an error); because strcpy() will write into the memory pointed to by its first argument, and a const pointer is a pointer whose data should not be written to.
In ANSI C I believe it should just work e.g.:
#include <string.h>
int main() {
const char *s="test";
unsigned const char *d = s;
char dest[1000];
strcpy(dest,d);
}
You could try adding a cast:
#include <string.h>
int main() {
const char *s="test";
unsigned const char *d = s;
char dest[1000];
strcpy(dest,(const char *) d);
}