why is string not implicit convertable to const(char*) ?

Jonathan M Davis jmdavisProg at gmx.com
Fri Jun 29 17:27:30 PDT 2012


On Saturday, June 30, 2012 02:12:22 mta`chrono wrote:
> does anyone know why string not implicit convertable to const(char*) ?
> 
> -------
> import core.sys.posix.unistd;
> 
> void main()
> {
>         // ok
>         unlink("foo.txt");
> 
>         // failed
>         string file = "bar.txt";
>         unlink(file);
> }
> 
> test.d(10): Error: function core.sys.posix.unistd.unlink (const(char*))
> is not callable using argument types (string)
> test.d(10): Error: cannot implicitly convert expression (file) of type
> string to const(char*)

Because it's _not_ const char*. It's an array. And passing a string directly 
to a C function (which is almost the only reason that you'd want a string to 
convert to a const char*) is generally _wrong_. Strings in D are _not_ zero-
terminated. String _literals_ are (they have a '\0' one character passed their 
end), so as it just so happens, if string implicitly converted to const char*, 
your code would work, but if your string had been created from anything other 
than a string literal, it would _not_ be zero terminated. Even concatenating 
two string literals results in a string which isn't zero-terminated. So, 
implictly converting strinvg to const char* would just cause bugs (in fact, it 
_used_ to work, and it was fixed so that it doesn't precisely because it's 
behavior which just causes bugs).

What you need to do is use std.string.toStringz. It converts a string to a 
zero-terminated string. It appends '\0' to the end of the string if it has to 
(which could result in the string having to be reallocated to make room for 
it), but if it can determine that it's unnecessary (which it can do at least 
some of the time with string literals), it'll just return the string's ptr 
property without doing any allocating. But since you _need_ that '\0', that's 
the best that you can do. Simply passing the string's ptr property to a C 
function would be wrong, since it's not zero-terminated.

Your function call should look like

unlink(toStringz(file));

Of course, you could just do std.file.remove(file), which ultimately does the 
same thing and does so on all platforms rather than just POSIX, but that's a 
separate issue from converting a string to a const char*.

- Jonathan M Davis


More information about the Digitalmars-d-learn mailing list