Jump to page: 1 2
Thread overview
char[] == null
Nov 18, 2015
Spacen Jasset
Nov 18, 2015
rsw0x
Nov 18, 2015
anonymous
Nov 19, 2015
Jonathan M Davis
Nov 19, 2015
Spacen Jasset
Nov 20, 2015
Kagamin
Nov 20, 2015
Maxim Fomin
Nov 18, 2015
Chris Wright
Nov 19, 2015
Meta
Nov 19, 2015
Chris Wright
Nov 19, 2015
anonymous
Nov 19, 2015
Chris Wright
Nov 19, 2015
Jack Applegame
Nov 19, 2015
Meta
Nov 19, 2015
Meta
Nov 19, 2015
Kagamin
Nov 19, 2015
BBaz
Nov 19, 2015
Jack Applegame
November 18, 2015
Should this be allowed? What is it's purpose? It could compare two arrays, but surely not that each element of type char is null?

char[] buffer;
if (buffer == null) {}
November 18, 2015
On Wednesday, 18 November 2015 at 20:57:08 UTC, Spacen Jasset wrote:
> Should this be allowed? What is it's purpose? It could compare two arrays, but surely not that each element of type char is null?
>
> char[] buffer;
> if (buffer == null) {}

slices aren't arrays
http://dlang.org/d-array-article.html
November 18, 2015
On 18.11.2015 22:02, rsw0x wrote:
> slices aren't arrays
> http://dlang.org/d-array-article.html

The language reference/specification [1] uses the term "dynamic array" for T[] types. Let's not enforce a slang that's different from that.


[1] http://dlang.org/arrays.html
November 18, 2015
On Wed, 18 Nov 2015 20:57:06 +0000, Spacen Jasset wrote:

> Should this be allowed? What is it's purpose? It could compare two arrays, but surely not that each element of type char is null?
> 
> char[] buffer;
> if (buffer == null) {}

'null' is a value of ambiguous type. The compiler finds a set of compatible types for them by applying known implicit conversions. 'null' can implicitly convert to 'char[]'.

Arrays, of course, are tuples consisting of a start pointer and length. A null array is essentially {ptr = null, length = 0}. Array equality is implemented as, roughly:

---
if (a.length != b.length) return false;
foreach (i, v; a) {
  if (v != b[i]) return false;
}
return true;
---

(That's not quite how it's implemented; it uses runtime functions and indirection. But it's the same algorithm.)

This shows us that all 0-length arrays are equal. Pretty much as we'd expect. So your code is equivalent to:

---
char[] buffer;
if (buffer.length == 0) {}
---
November 19, 2015
On Wednesday, 18 November 2015 at 23:53:01 UTC, Chris Wright wrote:
> ---
> char[] buffer;
> if (buffer.length == 0) {}
> ---

This is not true. Consider the following code:

import std.stdio;

void main()
{
	int[] a = [0, 1, 2];
        //4002E000 3
	writeln(a.ptr, " ", a.length);
        //Is not triggered, obviously
        assert(a == null);
	
	a.length = 0;
        //4002E000 0
	writeln(a.ptr, " ", a.length, " ", a);
        //Is not triggered, not as obvious
        assert(a == null);
}

There are cases when an array may have 0 length but a non-null pointer. If you want to check if an array's length is 0, you must explicitly check its length member. Checking if an array is equal to null only compares its pointer field to null. It does *not* check the length.
November 19, 2015
On Thu, 19 Nov 2015 03:53:46 +0000, Meta wrote:

> On Wednesday, 18 November 2015 at 23:53:01 UTC, Chris Wright wrote:
>> ---
>> char[] buffer;
>> if (buffer.length == 0) {}
>> ---
> 
> This is not true. Consider the following code:
> 
> import std.stdio;
> 
> void main()
> {
> 	int[] a = [0, 1, 2];
>          //4002E000 3
> 	writeln(a.ptr, " ", a.length);
>          //Is not triggered, obviously assert(a == null);
> 
> 	a.length = 0;
>          //4002E000 0
> 	writeln(a.ptr, " ", a.length, " ", a);
>          //Is not triggered, not as obvious assert(a == null);
> }
> 
> There are cases when an array may have 0 length but a non-null pointer. If you want to check if an array's length is 0, you must explicitly check its length member. Checking if an array is equal to null only compares its pointer field to null. It does *not* check the length.

I tested the behavior and it matches what I said earlier:

---
auto c = "hello world".dup;
auto b = c[0..0];
writeln(b == null);      // prints true
writeln(b.ptr == null);  // prints false
---

This is because array comparison is a memberwise comparison and not a reference comparison, as you can see more clearly with:

---
enum int[] a = [1, 2, 3];
writeln(a == a.dup);    // prints true
---

Or you can check the runtime's implementation of array equality at https://github.com/D-Programming-Language/druntime/blob/master/src/ object.d#L437 .

Just for fun, is an array ever not equal to itself?
November 19, 2015
On 19.11.2015 06:18, Chris Wright wrote:
> Just for fun, is an array ever not equal to itself?

Yes, when it contains an element that's not equal to itself, e.g. NaN.
November 19, 2015
On Thursday, 19 November 2015 at 03:53:48 UTC, Meta wrote:
> On Wednesday, 18 November 2015 at 23:53:01 UTC, Chris Wright wrote:
>> [...]
>
> This is not true. Consider the following code:
>
> import std.stdio;
>
> void main()
> {
> 	int[] a = [0, 1, 2];
>         //4002E000 3
> 	writeln(a.ptr, " ", a.length);
>         //Is not triggered, obviously
>         assert(a == null);
> 	
> 	a.length = 0;
>         //4002E000 0
> 	writeln(a.ptr, " ", a.length, " ", a);
>         //Is not triggered, not as obvious
>         assert(a == null);
> }
>
> There are cases when an array may have 0 length but a non-null pointer. If you want to check if an array's length is 0, you must explicitly check its length member. Checking if an array is equal to null only compares its pointer field to null. It does *not* check the length.

Really? http://dpaste.dzfl.pl/b11346e8e341
November 19, 2015
On Thursday, 19 November 2015 at 03:53:48 UTC, Meta wrote:
> On Wednesday, 18 November 2015 at 23:53:01 UTC, Chris Wright wrote:
>> ---
>> char[] buffer;
>> if (buffer.length == 0) {}
>> ---
>
> This is not true. Consider the following code:
>
> import std.stdio;
>
> void main()
> {
> 	int[] a = [0, 1, 2];
>         //4002E000 3
> 	writeln(a.ptr, " ", a.length);
>         //Is not triggered, obviously
>         assert(a == null);
> 	
> 	a.length = 0;
>         //4002E000 0
> 	writeln(a.ptr, " ", a.length, " ", a);
>         //Is not triggered, not as obvious
>         assert(a == null);
> }
>
> There are cases when an array may have 0 length but a non-null pointer. If you want to check if an array's length is 0, you must explicitly check its length member. Checking if an array is equal to null only compares its pointer field to null. It does *not* check the length.

Comparison is ok, weird behavior manifests in boolean context:
void main()
{
	int[] a = [0, 1, 2];
        //4002E000 3
        assert(a != null);
        assert(!!a); //passes, ok
	
	a.length = 0;
        //4002E000 0
        assert(a == null);
        assert(!!a); //still passes!
}
November 19, 2015
On Wednesday, November 18, 2015 22:15:19 anonymous via Digitalmars-d-learn wrote:
> On 18.11.2015 22:02, rsw0x wrote:
> > slices aren't arrays
> > http://dlang.org/d-array-article.html
>
> The language reference/specification [1] uses the term "dynamic array" for T[] types. Let's not enforce a slang that's different from that.
>
>
> [1] http://dlang.org/arrays.html

Exactly. T[] _is_ a dynamic array. Steven's otherwise wonderful article on arrays in D ( http://dlang.org/d-array-article.html ) made the mistake of calling the buffer that T[] points to on the GC heap (assuming that even does point to the GC heap) the dynamic array. And per the language spec, that's not true at all.

T[] is a dynamic array, whereas T[n] is a static array. The buffer referred to by T[] has no official name. And actually, the dynamic array really doesn't care whether it refers to a buffer on the GC heap, on that was malloced, a slice of a static array, etc. All of its operations are the same regardless, and all of the work. It's just that if the dynamic array does not refer to a buffer allocated on the GC heap for dynamic arrays, then it doesn't have any excess capacity for the dynamic array to grow into when you append to it, so appending to it forces the GC to reallocate its memory (as opposed to only having to reallocate sometimes when the buffer is already GC-allocated). And since the dynamic array itself does not manage its own memory, if you slice something other than GC-allocated memory to get a dynamic array, then it's up to you to make sure that you don't leak that memory or refer to it after it's been freed. However, every other aspect of T[] is identical regardless of what memory backs it, and most code really doesn't care what memory backs it.

As far as the D language is concern, T[] _is_ a slice of memory, but it's also a dynamic array, whereas the memory that it's slicing is _not_ a dynamic array.

- Jonathan M Davis

« First   ‹ Prev
1 2