The issue here is that C++ is a strongly typed language. You have to make sure the type on the right of an =
is the same as the type on the left (or there is some well defined conversion that allows the compiler to convert between types).
So we need to know what types literals are: Using a double quote creates a string literal of type char const[]
while using a single quote creates a character literal of type char const
.
You will have to bear with me on the const
part. That makes the discussion much more complicates so we will gloss over it initially.
We also need to know that when arrays are used in expressions they very easily decay into pointers. So it most situations the type of char const[]
will decay into char const*
.
This should work:
char const* p = "Hello"; // This is valid.
// Both left and right sides have the same type.
// After you consider the array decay into a pointer.
On the other hand
char const* p = 'H'; // The type on the right is `char const'
// While the type on the right has a pointer in it.
Now there are some automatic conversions at play here.
In the original C++03 the compiler was allowed to auto convert string literals from char const*
to char*
. This is a relic from the old C language that was not as strict on type checking as C++ is now. This allows for this:
char* p = "Hello"; // Because there is an auto conversion
// the compiler is allowed to make
// the conversion from one type to another
Note in later versions of C++ this conversion has been deprecated. SO the compiler will warn you that this is dangerous (because you have removed the const from the type you are allowed to modify it, but the underlying object can't be modified so if you try it will blow up the program).
So why can you assign char const
to a char
?
char x = 'X';
Here you are copying the original object char const
into an object of type char
this is perfectly valid. You can not alter or chance the literal but you are allowed to make copies of it. So you can easily remove the outer const
in an assignment expression.
char const* const y = "Hello";
char const* z = y; // We remove the outer const
// from a pointer. But the inner
// const (of the object being pointed
// at) can not be removed so easily.
// This works because z is allowed to
// to be changed but hold a value a pointer
// to a value that can not be changed.
Looking at your comment:
#include <iostream>
void test(char *str)
{
std::cout << str << std::endl;
}
int main()
{
test("Hello"); // This is allowed in C++
// Deprecated still means valid.
// Just not a good idea
// There is a allowed conversion from
// char const* to char* for string literals.
char const* x = "test";
test(x); // This is NOT allowed.
// You can not cast away this const.
}
Note: Technically a string literal is char const[]
. ie an array of const char. BUT when used in an expression arrays very easily decay into pointers and thus it is sometimes simpler to think of them as char const*
but this thinking is abstract and you should know the underlying exact type.