What exactly are the String literrals in D and how they work?

Steven Schveighoffer schveiguy at gmail.com
Sun Aug 15 16:43:27 UTC 2021


On 8/15/21 2:10 AM, rempas wrote:
> So when I'm doing something like the following: `string name = "John";`
> Then what's the actual type of the literal `"John"`?
> In the chapter [Calling C 
> functions](https://dlang.org/spec/interfaceToC.html#calling_c_functions) 
> in the "Interfacing with C" page, the following is said:
>> Strings are not 0 terminated in D. See "Data Type Compatibility" for 
>> more information about this. However, string literals in D are 0 
>> terminated.
> 
> Which is really interesting and makes me suppose that `"John"` is a 
> string literal right?
> However, when I'm writing something like the following: `char *name = 
> "John";`,
> then D will complain with the following message:
>> Error: cannot implicitly convert expression `"John"` of type `string` 
>> to `char*`
> 
> Which is interesting because this works in C. If I use `const char*` 
> instead, it will work. I suppose that this has to do with the fact that 
> `string` is an alias for `immutable(char[])` but still this has to mean 
> that the actual type of a LITERAL string is of type `string` (aka 
> `immutable(char[])`).
> 
> Another thing I can do is cast the literal to a `char*` but I'm 
> wondering what's going on under the hood in this case. Is casting 
> executed at compile time or at runtime? So am I going to have an extra 
> runtime cost having to first construct a `string` and then ALSO cast it 
> to a string literal?
> 
> I hope all that makes sense and the someone can answer, lol

Lots of great responses in this thread!

I wanted to stress that a string literal is sort of magic. It has extra 
type information inside the compiler that is not available in the normal 
type system. Namely that "this is a literal, and so can morph into other 
things".

To give you some examples:

```d
string s = "John";
immutable(char)* cs = s; // nope
immutable(char)* cs2 = "John"; // OK!
wstring ws = s; // nope
wstring ws2 = "John"; // OK!
```

What is going on? Because the compiler knows this is a string *literal*, 
it can modify the type (and possibly the data itself) at will to match 
what you are assigning it to. In the case of zero-terminated C strings, 
it allows usage as a pointer instead of a D array. In the case of 
different width strings (wstring uses 16-bit code-units), it can 
actually transform the underlying data to what you wanted.

Note that even when you do lose that "literal" magic by assigning to a 
variable, you can still rely on D always putting a terminating zero in 
the data segment for a string literal. So it's valid to just do:

```d
string s = "John";
printf(s.ptr);
````

As long as you *know* the string came from a literal.

-Steve


More information about the Digitalmars-d-learn mailing list