What exactly are the String literrals in D and how they work?
rempas
rempas at tutanota.com
Sun Aug 15 08:11:39 UTC 2021
On Sunday, 15 August 2021 at 07:43:59 UTC, jfondren wrote:
> ```d
> unittest {
> pragma(msg, typeof("John")); // string
> pragma(msg, is(typeof("John") == immutable(char)[])); //
> true
> }
> ```
Still don't know what "pragma" does but thank you.
> ```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
> }
> ```
That's interesting!
> ```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.
I mean that in C, we can assign a string literal into a `char*`
and also a `const char*` type without getting a compilation error
while in D, we can only assign it to a `const char*` type. I
suppose that's because of C doing explicit conversion. I didn't
talked about mutating a string literal
> 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
> }
> ```
>
Well, that one didn't worked out really well for me. Using
`.dup.ptr`, didn't added a null terminated character while
`cast(char*)` did. So I suppose the first way is more better when
you want a C-like `char*` and not a D-like `char[]`.
More information about the Digitalmars-d-learn
mailing list