In C and C++, when you make a string literal, there is implicitly created a variable of type char[]
with static storage duration to hold it. The string will be null-terminated as is consistent with C style.
The line
char* line2 = "hello";
is roughly equivalent to
static char __string_literal_line2[] = "hello";
// At top of program or something
...
char * line2 = __string_literal_line2;
So the char[]
implicitly decays to a char*
when you do it this way.
A wrinkle in this is that the array really is "const" in some sense and it is undefined behavior to try to modify it, but the C standard explicitly permits you to assign it to a char *
anyways, so that legacy code that is not const-correct will still compile, and to be compatible C++ also permits this.
It's sometimes really convenient if you are doing compile-time programming to take advantage of the "true form" of the string literal. For instance in this code sample:
Passing constexpr objects around
class str_const {
const char * const p_;
const std::size_t sz_;
public:
template <std::size_t N>
constexpr str_const( const char( & a )[ N ] )
: p_( a ), sz_( N - 1 ) {}
...
};
The str_const
object can now be constructed as a constexpr at compile time from a string literal, and it will know the size of the string literal, even though normally you need to iterate or use C library functions to determine that. That's because it receives the string literal as a char[]
rather than as a char *
, and it can bind to the length of the array as part of the template deduction. So these expressions are legal, and the str_const
object knows the lengths of the strings at compile-time:
str_const("foo");
str_const("foobar");
str_const("foobarbaz");