10

How to convert char* to const char* in C++? Why program 1 is working but program 2 can't?

Prog 1 (working):

char *s = "test string";
const char *tmp = s;
printMe(tmp);

void printMe(const char *&buf) {
    printf("Given Str = %s", buf);
}

Prog 2 (not working)

char *s = "test string";
printMe((const char *)s);     // typecasting not working

void printMe(const char *&buf) {
    printf("Given Str = %s", buf);
}

The error I receive:

x.cpp:10:15: warning: conversion from string literal to 'char *' is 
deprecated [-Wc++11-compat-deprecated-writable-strings]
char *s = "test string";
          ^
x.cpp:12:5: error: no matching function for call to 'printMe'
printMe(s);
^~~~~~~
x.cpp:6:6: note: candidate function not viable: no known conversion 
from 'char *' to 'const char *&' for 1st argument
void printMe(const char *&buf)
 ^
1 warning and 1 error generated.

Thanks.

Guy Avraham
  • 3,482
  • 3
  • 38
  • 50
M. Rock
  • 103
  • 1
  • 1
  • 8
  • 1
    That's not valid C, it's C++. And in *both* languages you're doing it wrong... The pointer `s` is a pointer to a *read-only* (`const` in C++) array of characters, so `s` should really be `const char *s = "test string";` – Some programmer dude Jun 19 '17 at 18:07
  • Ohh okay! I am sorry I am trying to compile using g++. let me change the title. – M. Rock Jun 19 '17 at 18:09
  • No tmp defined in Prog 2? – Stephan Lechner Jun 19 '17 at 18:12
  • I know @some programmer dude. But I am wondering is there way to convert char * to const char * or vice versa? – M. Rock Jun 19 '17 at 18:12
  • But why do you want to do that? `const char *` is stricter than `char *` so you can pass a `char *` argument to a function with a `const char *` parameter. – SHG Jun 19 '17 at 18:14
  • "I am wondering is there way to convert char * to const char * or vice versa?" --> @M.Rock Is not the "working" `const char *tmp = s;` converting a `char *` to a `const char *`? So apparently one of those paths is successful. – chux - Reinstate Monica Jun 19 '17 at 18:15
  • @DavidBowling: No. It's void printMe(const char *&buf) only. – M. Rock Jun 19 '17 at 18:17
  • `(const char *)s;` does successfully convert a `char *` to a `const char *`, yet `printMe(const char *&buf);` needs something more. – chux - Reinstate Monica Jun 19 '17 at 18:24
  • 2
    const char *&buf, the & means it's bounded to a variable, in the first case it's tmp. In the second case since you don't have tmp, it cannot convert char* to a bounded variable. If all printMe does is printf, you don't need const char*& buf, you just need const char* buf. – Tony J Jun 19 '17 at 18:24
  • Thanks @TonyJ for explanation. can you please tell me what is the difference between `const char *&` and `const char *` and `const char &` ? – M. Rock Jun 19 '17 at 18:35

1 Answers1

6

printMe takes an lvalue reference to a mutable pointer to const char.

In your first example, tmp is an lvalue of type mutable pointer to const char, so a reference can be bound to it without issue.
In your second example, (const char*)s creates a temporary const char* object. Lvalue references to mutable objects can't bind to temporaries, so you get an error. If you change printMe to take a const char* const& then the call will succeed with or without the explicit cast.

void printMe(const char * const& buf) {
    printf("Given Str = %s", buf);
}

int main() {
    char s[] = "test string";
    printMe(s);
}

Live on Coliru

Of course, if you don't want to alter the object (the pointer) passed into printMe, then there's no reason to use a reference at all. Just make it take a const char*:

void printMe(const char * buf) {
    printf("Given Str = %s", buf);
}

int main() {
    char s[] = "test string";
    printMe(s);
}

Live on Coliru

In the end, this is the same reason something like this:

void doSomething(const std::string& s) {}
int main() {
    doSomething("asdf");
}

works while this:

void doSomething(std::string& s) {}
int main() {
    doSomething("asdf");
}

does not. A temporary object is created, and the reference to non-const object can't bind to the temporary.

Miles Budnek
  • 28,216
  • 2
  • 35
  • 52
  • Thanks @Miles for clarification. Can you please tell me difference between `const char *&` and `const char *` and `const char &` ? – M. Rock Jun 19 '17 at 18:53
  • They are: a reference to a pointer to a const char, a pointer to a const char, and a reference to a const char, respectively. Pointers are full-fledged objects that store a memory address, while references are conceptually just new names for existing objects. See [What are the differences between a pointer variable and a reference variable in C++?](https://stackoverflow.com/questions/57483/what-are-the-differences-between-a-pointer-variable-and-a-reference-variable-in) for more info. – Miles Budnek Jun 19 '17 at 18:58
  • Thanks a lot @Miles! – M. Rock Jun 19 '17 at 19:24