What exactly are the String literrals in D and how they work?
jfondren
julian.fondren at gmail.com
Sun Aug 15 07:43:59 UTC 2021
On Sunday, 15 August 2021 at 06:10:53 UTC, rempas wrote:
> So when I'm doing something like the following: `string name =
> "John";`
> Then what's the actual type of the literal `"John"`?
```d
unittest {
pragma(msg, typeof("John")); // string
pragma(msg, is(typeof("John") == immutable(char)[])); // true
}
```
> 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.
```d
void zerort(string s) {
assert(s.ptr[s.length] == '\0');
}
unittest {
zerort("John"); // assertion success
string s = "Jo";
s ~= "hn";
zerort(s); // assertion failure
}
```
If a function takes a string as a runtime parameter, it might not
be NUL terminated. This might be more obvious with substrings:
```d
unittest {
string j = "John";
string s = j[0..2];
assert(s == "Jo");
assert(s.ptr == j.ptr);
assert(s.ptr[s.length] == 'h'); // it's h-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.
Well, kinda:
```c
void mutate(char *s) {
s[0] = 'X';
}
int main() {
char *s = "John";
mutate(s); // segmentation fault
}
```
`char*` is just the wrong type, it suggests mutability where
mutability ain't.
> 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.
The same thing as in C:
```d
void mutate(char *s) {
s[0] = 'X';
}
void main() {
char* s = cast(char*) "John";
mutate(s); // program killed by signal 11
}
```
> Is casting executed at compile time or at runtime?
Compile-time. std.conv.to is what you'd use at runtime. Here
though, what you want is `dup` to get a `char[]`, which you can
then take the pointer of if you want:
```d
unittest {
char* s = "John".dup.ptr;
s[0] = 'X'; // no segfaults
assert(s[0..4] == "Xohn"); // ok
}
```
> 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
More information about the Digitalmars-d-learn
mailing list