Search code examples
c++pointersstring-literals

Can I assign a pointer to char pointer directly to a string literal?


I would like to know if I can assign a pointer to pointer to char directly to a string literal without first assigning the string literal to an lvalue pointer first. Usually if an argument takes a pointer to something, you can pass the address of the object using &, and a string literal seems to be (or at least decays to) a char pointer because you can assign them to char pointers. This is why I expected one of the following to work:

const char ** ppchar = &"StringLiteral"; // This doesn't compile

const char ** ppchar = (const char **)&"StringLiteral"; // This compiles, but...

std::cout << *ppchar;   // Throws an exception

I expected at least the second one of these to work, because "StringLiteral" seems to me to at least decay to a pointer, so in:

const char** ppchar = (const char**) &"StringLiteral";

The first pointer would point to the address of the string literal. If the string literal is assigned to an lvalue pointer first, the first pointer would be pointing to the second pointer, which is essentially holding its address. Seems the same to me.

Edit: Also, it seems I can do:

const char * _pptr = (const char*)&"StringLiteral";
std::cout << _pptr; // Prints "Hello"

So it doesn't seem to a rule against assigning directly to the string literal.

Edit: As is so obvious to many, I have my levels of indirection wrong. This is explained by Vlad from Moscow in his answer. In:

const char ** pptr = (const char**)&"StringLiteral";

The compiler expects pptr to point to something that stores the address of a char, whereas I've assigned it to the address of the "StringLiteral" itself, which means when I cout it dereferences the first pointer to find which address find the char. The problem is it's pointing directly to the address of the "StringLiteral", meaning it uses the value of the first letter of "StringLiteral" as the address to go to to find the char, basically it'll use "S" as the address to go to. Hate being so thick.


Solution

  • This expression

    &"StringLiteral"
    

    has the type const char( * )[14] in C++ and char ( * )[14] in C because the string literal has respectively the type const char[14] or char[14].

    So you may not assign such a pointer to an object of the type const char ** or char ** because the pointers are incompatible.

    And if you will try to use a casting as in this declaration

    const char** ppchar = (const char**) &"StringLiteral";
    

    nevertheless dereferencing this pointer like *ppchar does not make sense because instead of the object of the type char * as it would be expected you will get the value that corresponds to the value of the first character of the string literal instead of an address value.

    You could for example at first convert the string literal to the type const char * (or char * in C) the following way

    StringLiteral + 0
    

    because in such expressions a string literal is converted to pointer to its first character. However you may not apply the unary operator & to this expression like

    &( StringLiteral + 0 )
    

    to get an object of the type const char ** because you may not apply the operator to an rvalue.

    So what you could do is the following

    const char *pchar = "StringLiteral";
    const char **ppchar = &pchar;