Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C++, Need Reason for error : cannot convert parameter 1 from 'char *' to 'const char *&'

Whey we cannot Convert pointer to a character ->TO-> a reference to a pointer to a constant character

I am interested in knowing the reason of syntax error when we call foo_ptr. When foo_char is allowed why not foo_ptr.
[Update 1.] I would be happy in knowing the reason that foo_char() is working, why foo_ptr() is not working .. What happens when pointer come in the picture.

[Update 2.] Didnt work in Dev C++ compiler version 4.9.9.2 too ..

//code
//OS : Win XP
//Env: VC++ 2008 

//NOT ALLOWED
void foo_ptr(const char * & ptr) //reference to a pointer to a constant character         
{         
        return;         
}        


//allowed        
void foo_char(const char & p_Char) //reference to a constant character        
{         
        return;        
}        

int main()        
{        
        char ch = 'd';        
        char *ptr =  "anu";        

        foo_char(ch);         
        foo_ptr(ptr); //NOT ALLOWED syntax error, vc++, 2008        

        return 0;        
}        
like image 852
anubhav16 Avatar asked Oct 21 '11 14:10

anubhav16


2 Answers

Suppose you had

void foo_ptr(const char * & ptr)
{         
    ptr = "readonlystring";
}        

You now call it as

    char *ptr;
    foo_ptr(ptr);
    *ptr = 0;

Suppose no error were raised. You are writing to a read-only string, violating the type system without any casts.

This is basically the CV version of How come a pointer to a derived class cannot be passed to a function expecting a reference to a pointer to the base class?.

like image 88
Raymond Chen Avatar answered Oct 22 '22 20:10

Raymond Chen


Revised with more examples: Raymond Chen provides the correct answer. By passing a non const pointer (char *) as reference parameter of a const pointer (foo_ptr(const char * &param)) you risk returning a const pointer type (const char *) and the compiler won't allow you to do that.

Here's Raymond Chen's example of that, but I tried to explain how things would go wrong if it compiled by adding additional comments and code:

void foo_ptr(const char * & ptr)
{         
    //Valid assignment, and the char * is now pointing to a const
    //array of "readonlystring"
    ptr = "readonlystring";
}   

...
//inside main
char *ptr = malloc(10*sizeof(char));
//See you can edit ptr, it's not const.
ptr[0] = 'a';
ptr[1] = 'b';
//this should not compile, but lets assume it did..
foo_ptr(ptr);
//Oh no, now ptr[0] is 'r' inside of constant memory,
//but now since ptr isn't declared const here I can overwrite it!
//But luckily most (all?) compilers actually fail to compile this code.
ptr[0] = 'b';

But if you change your parameter so you can't affect the value that the pointer points to then the compiler will let you past in a non-const because there is no chance a const valued pointer is returned.

By placing the keyword const AFTER the * in your parameter deceleration you do just that. That means change:

void foo_ptr(const char * & ptr)

to

void foo_ptr(const char * const & ptr)

and your compiler will be happy.

Now you would not be able to do something like ptr = "readonlystring" in the above example because that would never compile now. Based on your question that should be OK because you would not be able to do the assignment to a const char & in your original example.

like image 33
James Avatar answered Oct 22 '22 21:10

James