On 10/2/12 7:11 AM, Don Clugston wrote:
The problem
-----------
String literals in D are a little bit magical; they have a trailing \0.
[snip]
I don't mean to be Debbie Downer on this because I reckon it addresses
an issue that some have, although I never do. With that warning, a few
candid opinions follow.
First, I think zero-terminated strings shouldn't be needed frequently
enough in D code to make this necessary.
Second, a simple and workable solution to this would be to address the
matter dynamically: make toStringz opportunistically look whether
there's a \0 beyond the end of the string, EXCEPT when the string
happens to end exactly at a page boundary (in which case accessing
memory beyond the end of the string may produce a page fault). With this
simple dynamic test we don't need precise and stringent rules for the
implementation.
Third, the complex set of rules proposed pushes the number of cases in
which the \0 is guaranteed, but doesn't make for a clear and easy to
remember boundary. Therefore people will need to remember some more
rules to make sure they can, well, avoid a call to toStringz.
On 10/2/12 10:55 AM, Regan Heath wrote:
Recent discussions on the zero terminated string problems and
inconsistency of string literals has me, again, wondering why D
doesn't have a 'type' to represent C's zero terminated strings. It
seems to me that having a type, and typing C functions with it would
solve a lot of problems.
[snip]
I am probably missing something obvious, or I have forgotten one of
the array/slice complexities which makes this a nightmare.
You're not missing anything and defining a zero-terminated type is
something I considered doing and have been highly interested in. My
interest is motivated by the fact that sentinel-terminated structures
are a very interesting example of forward ranges that are also
contiguous. That sets them apart from both singly-linked lists and
simple arrays, and gives them interesting properties.
I'd be interested in defining the more general:
struct SentinelTerminatedSlice(T, T terminator)
{
private T* data;
...
}
That would be a forward range and the instantiation
SentinelTerminatedSlice!(char, 0) would be CString.
However, so far I held off of defining such a range because C-strings
are seldom useful in D code and there are not many other compelling
examples of sentinel-terminated ranges. Maybe it's time to dust off that
idea, I'd love it if we gathered enough motivation for it.
Andrei