2

So, I'm aware that a string literal has a type of const char[N]. And I'm also aware that if we got a const char[] parameter in some function, compiler automatically converts it to const char*.

But why do I always get compiler error messages saying that a string literal has a type of const char*?

Here's a few examples:

void f(int x) {}
int main()
{
    f("Hello");
    return 0;
}

ERROR: invalid conversion from 'const char*' to 'int'

void f() {
    throw "Hello";
}
int main()
{
    try{ f(); } catch (int x) { std::cout << "No\n";}
    return 0;
}

In terminal: terminate called after throwing an instance of 'char const*'

EDIT: I'm using GNU GCC.

domdrag
  • 541
  • 1
  • 4
  • 13
  • @Jabberwocky https://stackoverflow.com/questions/12517983/what-is-the-datatype-of-string-literal-in-c – domdrag Mar 18 '20 at 11:27
  • 4
    My compiler says `candidate function not viable: no known conversion from 'const char [6]' to 'int' for 1st argument` – Eljay Mar 18 '20 at 11:27
  • @GRRohman Right, so that link should answer your question. – Jabberwocky Mar 18 '20 at 11:28
  • Does this answer your question? [What is the datatype of string literal in C++?](https://stackoverflow.com/questions/12517983/what-is-the-datatype-of-string-literal-in-c) – Jabberwocky Mar 18 '20 at 11:28
  • @Jabberwocky Sadly, no . – domdrag Mar 18 '20 at 11:29
  • I suspect it's a (small) gcc bug. The Microsoft compilers (at least recent versions) and clang produce the correct error message with respect to this SO question: https://stackoverflow.com/questions/12517983/what-is-the-datatype-of-string-literal-in-c – Jabberwocky Mar 18 '20 at 11:33

1 Answers1

5

Why does const char[] get converted to const char* all the time?

Generally, because there is another rule closely related to the function parameter adjustment that you mentioned:

[conv.array] Array-to-pointer conversion

An lvalue or rvalue of type “array of N T” or “array of unknown bound of T” can be converted to a prvalue of type “pointer to T”. The temporary materialization conversion ([conv.rval]) is applied. The result is a pointer to the first element of the array.

[basic.lval] Value category

Whenever a glvalue appears as an operand of an operator that expects a prvalue for that operand, the lvalue-to-rvalue, array-to-pointer, or function-to-pointer standard conversions are applied to convert the expression to a prvalue.

Colloquially, this implicit conversion is called pointer decaying.

The error message appears to describe an attempt to convert this intermediary result of lvalue-to-rvalue conversion to the parameter type.

In terminal: terminate called after throwing an instance of 'char const*'

In this particular case of exception throwing, there is a specific rule, which is essentially same as pointer decaying, but in context of a throw:

[expr.throw] Throwing an exception

Evaluating a throw-expression with an operand throws an exception; the type of the exception object is determined by removing any top-level cv-qualifiers from the static type of the operand and adjusting the type from “array of T” or function type T to “pointer to T”.

So, the adjusted type of the exception object is in fact const char*, and it is this uncaught object that the compiler generated message describes.


For completeness, here is the parameter adjustment rule that you knew:

[dcl.fct] Functions

... After determining the type of each parameter, any parameter of type “array of T” or of function type T is adjusted to be “pointer to T”

P.S. there is also an analogous adjustment rule for exception handlers:

[except.handle] Handling an exception

A handler of type “array of T” or function type T is adjusted to be of type “pointer to T”.

eerorika
  • 232,697
  • 12
  • 197
  • 326
  • This explains the exception messsage, but I don't see how this explains why gcc refers to the string literal as `const char*`, while msvc and clang refer to it (more correctly?) as `const char[6]`. – Lukas-T Mar 18 '20 at 11:45
  • 1
    @churill GCC refers to the adjusted type of the thrown exception object, and Clang refers to the type of the expression before adjustment. In my opinion, both are correct and I don't think it's clear which is more useful. – eerorika Mar 18 '20 at 11:47
  • @eerorika Does that "automatical" array-to-pointer conversion happen using temporary objects? If not , how does the conversion happen on slightly lower level ? – domdrag Mar 18 '20 at 12:56
  • @domocar1 It does happen using temporary objects too. – eerorika Mar 18 '20 at 13:18
  • Too ? What's the alernative ? I haven't caught it from your answer, maybe it is due to my lack of knowledge. – domdrag Mar 18 '20 at 13:25
  • @domocar1 alternative is non-temporaries. Such as the string literal in your example. – eerorika Mar 18 '20 at 13:25