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[]`.

Reply via email to