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