string types: const(char)[] and cstring

Walter Bright newshound1 at digitalmars.com
Sun May 27 12:06:06 PDT 2007


Derek Parnell wrote:
> See, this is what is weird ... I can have an invariant string which can be
> changed, thus making it not really invariant in the English language sense.
> I'm still thinking that "invariant" means "does not change ever". 

Where you're going wrong is that there are two parts to a dynamic array 
- the contents of the array, and the ptr/length values of the array.

	invariant(char)[]

immutalizes (look ma! I coined a new word!) only the contents of the array.

	invariant(char[])

immutalizes the contents and the ptr/length values.


> But it seems that I'm wrong ...
> 
>  invariant char[] x; 
>  x = "abc".dup;  // The string 'x' now contains "abc";
>  x = "def".dup;  // The string (which is not supposed to change
>                  // i.e invariant) has been changed to "def".
> 
> Now this is counter-intuitive (read: *WEIRD*), no?

The first issue is that you've confused:
	invariant char[] x;
with:
	invariant(char)[] x;

Remember, there are TWO parts to an array, and the invariantness can be 
controlled for either independently, or both. This isn't different from 
in C++ there are two parts to a char*, the char part, and the pointer part.

> Okay, I've got that now ... but how to remember that two terms that mean
> the same in English actually mean different things in D <G>

English is imprecise and ambiguous, that's why we have mathematical 
languages, and programming languages.

>   invariant char[] x; // The data pointed to by 'x' cannot be changed
>                       // by anything anytime during the execution
>                       // of the program.
>                       // (So how do I populate it then? Hmmmm ...)

You can't populate an invariant(char)[] array (which is what you meant, 
not invariant char[]). The way to get one is to cast an existing array 
to invariant.

>   const char[] y;    // The data pointed to by 'y' cannot be changed
>                      // by anything anytime during the execution
>                      // of the program when using the 'y' variable,
>                      // however using another variable that also
>                      // refers to y's data, or some of it, is ok.

Yes, but here again, const(char)[].

> For example ...
> 
>   void func (const char[] a, char[] b)
>   {
>         a[0] = 'a'; // fails
>         b[0] = 'a'; // succeeds
>   }
> 
>   char[] y = "def".dup;
>   func( y, y);

Yup, that's the aliasing issue with const.


> Thanks. So 'final' means that it can be changed (from its initial default
> value) once and only once.

No. 'final' means it is set only at initialization.

> /* --- Scenario #1 --- */
>   final int r;
>   r = randomer(); // succeeds
Nope, this fails. Try:
	final int r = randomer();
>   foo(); // fails 
> 
>   int randomer() { 
>       // Get a random integer between -100 and 100.
>       return cast(int)(std.random.rand() % 201) - 100; 
>   }
>   void foo() { 
>     r = randomer(); // success depends on whether or not 'r' 
>                     // has already been set.
No, this assignment always fails.
>   }
> 

> Is this a run-time check or a compile time one?

Compile time.

> If run-time, would it be
> possible to somehow 'unfinal' a variable using some implementation
> dependant trickery.

Yes, but the result is undefined behavior. Just like if you went around 
the typing system and converted an int into a pointer, and tried to 
access data with it. You can do it, but you're on your own with that.


> I have no real knowledge of C++ or its const, and I'm still weirded out by
> it all <G>

I'm beginning to realize that unless one understands how types are 
represented at run time, one will never understand const.



More information about the Digitalmars-d-announce mailing list