Let's look at the sentences from your example, step by step.
In this sentence
int *a;
you declared a variable a as a pointer to an object of type int
In this sentence
char *b;
you declared b as a pointer to an object of type char
In this sentence
a = new int(10);
An object was created in the dynamic memory of type int , which was initialized to the value 10.
In this sentence
b = "bla bla bla";
on the left side of an expression with an assignment operator is variable with type char * . The right side of this expression uses the string literal "bla bla bla" . C ++ string literals have types of constant character arrays.
(C ++ Standard, 2.14.5 String literals)
8 Ordinary string literals and UTF-8 string literals are also referred to as narrow string literals. A narrow string literal has a type “array of const char” , where there is a storage storage duration (3.7).
The string literal "bla bla bla" has the type const char [12] . In expressions, arrays are implicitly converted to pointers to their first element.
According to C ++ standard (4.2 Array-to-pointer conversion)
1 Analogue of the “array of NT” or “the array of unknown bound of T” can be converted. The result is a pointer to the first element of the array .
Thus, in the above sentence, the right side of an expression with an assignment operator uses a value of the type const char * , which points to the first character of the string literal "bla bla bla" . That is, there is an attempt to assign the value of a pointer of type char * to the value of a pointer of type const char * . Since there is no implicit conversion from a pointer type to a constant object to a pointer type to a non-constant object, the compiler must issue a diagnostic message.
It would be correct to declare the variable b as follows.
const char *b;
Then the above assignment statement would be correct, and the variable b would be assigned the address of the first character of the string literal standing on the right side of the expression from the assignment sign.
This offer
b = "bla bla bla";
in fact, equivalent to the following sentence
b = &"bla bla bla"[0];
In this sentence
cout << "a: " << *a << endl;
the integer value addressed by the pointer a is output to the console.
It would be more correct to write
cout << "*a: " << *a << endl; ^^^
In this sentence
cout << "b: " << b << endl;
provided that the compiler somehow generated the object module, despite the error I mentioned above, will output a string literal to the console, since for char * pointers the operator << overloaded so that instead of the value of the pointer itself, it outputs the contents of the memory addressed by this pointer as a string.
If you want to display exactly the value of the pointer itself, then you should write either
cout << "b: " << ( void * )b << endl;
or
cout << "b: " << static_cast<void *>( b ) << endl;
And if the variable b was declared with the const qualifier, then
cout << "b: " << ( const void * )b << endl;
or
cout << "b: " << static_cast<const void *>( b ) << endl;