www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - Implicit dereferencing

reply =?UTF-8?B?Ikx1w61z?= Marques" <luismarques gmail.com> writes:
Consider this (non-portable) code:

{
     int[2] a;
     int[2] b;
     int[2] *c;
     c = &a;

     c[0] = 7;
     assert(a[0] == 7); // OK, as expected

     c[1] = 42;
     assert(b[0] == 42); // do we really want this semantics?
}

Because indexing c automatically dereferences the pointer, "c[0] 
= 7" assigns to a[0], as expected. This is the same as "(*c)[0] = 
7", which is useful.

But "c[1] = 42" is equivalent to "(*(c+1)) = 42", which might not 
be obvious. In this case it ends writing to b[0]. Why not make 
the semantics be ((*c)+1) = 42, instead? Wouldn't that be more 
useful?

Also, why don't we have pointer dereferencing for AAs?

{
     struct Foo { int f; }

     // given that this works...
     Foo x;
     Foo *y = &x;
     x.f = 1;
     y.f = 2; // implicit dereferencing

     // coudln't this be made to work?...
     int[string] c;
     int[string] *d;
     d = &c;
     c["foo"] = 1;
     d["foo"] = 2; // fails, dereferencing must be explicit
     (*d)["foo"] = 2; // works, of course
}
Apr 01 2013
next sibling parent "Steven Schveighoffer" <schveiguy yahoo.com> writes:
On Mon, 01 Apr 2013 20:07:30 -0400, Lu=C3=ADs Marques <luismarques gmail=
.com>  =

wrote:

 Consider this (non-portable) code:

 {
      int[2] a;
      int[2] b;
      int[2] *c;
      c =3D &a;

      c[0] =3D 7;
      assert(a[0] =3D=3D 7); // OK, as expected

      c[1] =3D 42;
      assert(b[0] =3D=3D 42); // do we really want this semantics?
 }

 Because indexing c automatically dereferences the pointer, "c[0] =3D 7=

 assigns to a[0], as expected. This is the same as "(*c)[0] =3D 7", whi=

 is useful.

This is not what is happening. If you add: writeln(a); you will see: 7, 7 You see, indexing does NOT dereference the pointer, it's an index for th= at = pointer. c[0] means *(c + 0). A pointer is essentially an unchecked = slice, with undefined length. This is how it works in C also. c[1] is the same as *(c + 1), completely consistent (and also sets b to = = 42, 42) -Steve
Apr 01 2013
prev sibling next sibling parent =?UTF-8?B?Ikx1w61z?= Marques" <luismarques gmail.com> writes:
On Tuesday, 2 April 2013 at 02:52:48 UTC, Steven Schveighoffer 
wrote:
 You see, indexing does NOT dereference the pointer, it's an 
 index for that pointer.  c[0] means *(c + 0).  A pointer is 
 essentially an unchecked slice, with undefined length.  This is 
 how it works in C also.

 c[1] is the same as *(c + 1), completely consistent (and also 
 sets b to 42, 42)

OK, I think I see where I went astray. I was a case of bad induction from a few tests :-) So, I guess what is happening is the following, right? int[2] a; int[2] *c; c = &a; c[0] = 7; // same thing as below a = 7; // same thing above (cast(int*) c)[0] = 7; // but different from this I verified that c is a pointer to a.ptr, I guess what I didn't consider is that because c points to int[2], the assignment becomes the same as a = 7, and not a[0] = 7. Still, what do you think of the struct vs AA automatic pointer dereferencing?
Apr 01 2013
prev sibling next sibling parent "Steven Schveighoffer" <schveiguy yahoo.com> writes:
On Mon, 01 Apr 2013 23:23:49 -0400, Lu=C3=ADs Marques <luismarques gmail=
.com>  =

wrote:

 On Tuesday, 2 April 2013 at 02:52:48 UTC, Steven Schveighoffer wrote:
 You see, indexing does NOT dereference the pointer, it's an index for=


 that pointer.  c[0] means *(c + 0).  A pointer is essentially an  =


 unchecked slice, with undefined length.  This is how it works in C al=


 c[1] is the same as *(c + 1), completely consistent (and also sets b =


 42, 42)

OK, I think I see where I went astray. I was a case of bad induction =

 from a few tests :-)
 So, I guess what is happening is the following, right?

      int[2] a;
      int[2] *c;
      c =3D &a;

      c[0] =3D 7;  // same thing as below
      a =3D 7;      // same thing above

      (cast(int*) c)[0] =3D 7; // but different from this

 I verified that c is a pointer to a.ptr, I guess what I didn't conside=

 is that because c points to int[2], the assignment becomes the same as=

 =3D 7, and not a[0] =3D 7.

 Still, what do you think of the struct vs AA automatic pointer  =

 dereferencing?

a pointer defines indexing. To have implicit dereferencing for indexing= = on any pointer type would not be good. For example: string[int][2] aas; string[int] *aaptr =3D aas.ptr; auto x =3D aaptr[1]; If x is not a pointer to aas[1], then you would have to access it using = = *(aaptr + 1), which would suck. Plus it would make pointers to indexed = = types inconsistent with all pointers to types that don't define indexing= . -Steve
Apr 01 2013
prev sibling next sibling parent =?UTF-8?B?Ikx1w61z?= Marques" <luismarques gmail.com> writes:
On Tuesday, 2 April 2013 at 03:36:04 UTC, Steven Schveighoffer 
wrote:
 Plus it would make pointers to indexed types inconsistent with 
 all pointers to types that don't define indexing.

Yeah, of course you're right... Taking a step back, I think the problem here is that I wanted to have multiple references to the contents of an associative array. With a regular array, while you can't *store* a reference to the array "header" (ptr, length) without using pointers, you can have another array pointing to the same content. I guess you can't do something like that with an associative array, right? (mm... that kinda breaks the ideia of an AA as a more general array)
Apr 01 2013
prev sibling next sibling parent "Steven Schveighoffer" <schveiguy yahoo.com> writes:
On Tue, 02 Apr 2013 00:12:37 -0400, Lu=C3=ADs Marques <luismarques gmail=
.com>  =

wrote:

 On Tuesday, 2 April 2013 at 03:36:04 UTC, Steven Schveighoffer wrote:
 Plus it would make pointers to indexed types inconsistent with all  =


 pointers to types that don't define indexing.

Yeah, of course you're right... Taking a step back, I think the problem here is that I wanted to have =

 multiple references to the contents of an associative array. With a  =

 regular array, while you can't *store* a reference to the array "heade=

 (ptr, length) without using pointers, you can have another array  =

 pointing to the same content. I guess you can't do something like that=

 with an associative array, right? (mm... that kinda breaks the ideia o=

 an AA as a more general array)

An AA is a pImpl, meaning a pointer to implementation. A simple copy is= = an alias. HOWEVER, there is one horrible caveat. You must have assigned an elemen= t = at least once in order to alias: int[int] aa1; // pImpl initialized to null int[int] aa2; // pImpl initialized to null aa2 =3D aa1; // just assigns null to aa2 aa1[1] =3D 1; // allocates and initializes aa2[1] =3D 2; // allocates and initializes separate instance assert(aa1[1] =3D=3D 1 && aa2[1] =3D=3D 2); aa2 =3D aa1; // NOW they are aliased assert(aa2[1] =3D=3D 1); aa2[1] =3D 2; assert(aa1[1] =3D=3D 2); -Steve
Apr 01 2013
prev sibling next sibling parent kenji hara <k.hara.pg gmail.com> writes:
--089e0112c5125174e004d95979af
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: quoted-printable

2013/4/2 <luismarques gmail.com>" puremagic.com <"\"Lu=C3=ADs".Marques">

 On Tuesday, 2 April 2013 at 02:52:48 UTC, Steven Schveighoffer wrote:

 You see, indexing does NOT dereference the pointer, it's an index for
 that pointer.  c[0] means *(c + 0).  A pointer is essentially an uncheck=


 slice, with undefined length.  This is how it works in C also.

 c[1] is the same as *(c + 1), completely consistent (and also sets b to
 42, 42)

OK, I think I see where I went astray. I was a case of bad induction from a few tests :-) So, I guess what is happening is the following, right? int[2] a; int[2] *c; c =3D &a; c[0] =3D 7; // same thing as below a =3D 7; // same thing above

These are doing that element-wise assignment. c[0][] =3D 7; // same as c[0][0] =3D c[0][1] =3D 7; a[] =3D 7; // same as a[0] =3D a[1] =3D 7; As a side note:
From 2.063, lack of [] for array operation would be warned with -w switch.

So, there is no "implicit dereferencing". Kenji Hara --089e0112c5125174e004d95979af Content-Type: text/html; charset=UTF-8 Content-Transfer-Encoding: quoted-printable <div dir=3D"ltr"><div class=3D"gmail_extra"><div class=3D"gmail_quote">2013= /4/2 &lt;<a href=3D"mailto:luismarques gmail.com">luismarques gmail.com</a>= &gt;&quot; <a href=3D"http://puremagic.com">puremagic.com</a> <span dir=3D"= ltr">&lt;<a href=3D"mailto:&quot;\&quot;Lu=C3=ADs&quot;.Marques&quot;" targ= et=3D"_blank">&quot;\&quot;Lu=C3=ADs&quot;.Marques&quot;</a>&gt;</span><br> <blockquote class=3D"gmail_quote" style=3D"margin-top:0px;margin-right:0px;= margin-bottom:0px;margin-left:0.8ex;border-left-width:1px;border-left-color= :rgb(204,204,204);border-left-style:solid;padding-left:1ex"><div class=3D"i= m"> On Tuesday, 2 April 2013 at 02:52:48 UTC, Steven Schveighoffer wrote:<br> <blockquote class=3D"gmail_quote" style=3D"margin-top:0px;margin-right:0px;= margin-bottom:0px;margin-left:0.8ex;border-left-width:1px;border-left-color= :rgb(204,204,204);border-left-style:solid;padding-left:1ex"> You see, indexing does NOT dereference the pointer, it&#39;s an index for t= hat pointer. =C2=A0c[0] means *(c + 0). =C2=A0A pointer is essentially an u= nchecked slice, with undefined length. =C2=A0This is how it works in C also= .<br> <br> c[1] is the same as *(c + 1), completely consistent (and also sets b to 42,= 42)<br> </blockquote> <br></div> OK, I think I see where I went astray. I was a case of bad induction from a= few tests :-)<br> So, I guess what is happening is the following, right?<br> <br> =C2=A0 =C2=A0 int[2] a;<div class=3D"im"><br> =C2=A0 =C2=A0 int[2] *c;<br> =C2=A0 =C2=A0 c =3D &amp;a;<br> <br></div> =C2=A0 =C2=A0 c[0] =3D 7; =C2=A0// same thing as below<br> =C2=A0 =C2=A0 a =3D 7; =C2=A0 =C2=A0 =C2=A0// same thing above<br></blockqu= ote><div><br></div><div>These are doing that element-wise assignment.</div>= <div><br></div><div>=C2=A0 =C2=A0 c[0][] =3D 7; =C2=A0//=C2=A0same as=C2=A0= c[0][0] =3D c[0][1] =3D 7;</div><div>=C2=A0 =C2=A0 a[] =3D 7; =C2=A0 =C2=A0= =C2=A0// same as a[0] =3D a[1] =3D 7;</div> <div><br></div><div>As a side note:</div><div>From 2.063, lack of=C2=A0[]= =C2=A0for array operation would be warned with -w switch.</div><div>=C2=A0<= br></div><div>So, there is no &quot;implicit dereferencing&quot;.=C2=A0</di= v><div><br></div><div> Kenji Hara</div></div></div></div> --089e0112c5125174e004d95979af--
Apr 01 2013
prev sibling next sibling parent =?UTF-8?B?QWxpIMOHZWhyZWxp?= <acehreli yahoo.com> writes:
On 04/01/2013 05:07 PM, "Luís Marques" <luismarques gmail.com>" wrote:> 
Consider this (non-portable) code:

Perhaps it is obvious to everyone but allow me still: It is not 
non-portable code, but its behavior is undefined.

 {
      int[2] a;
      int[2] b;
      int[2] *c;

c is a pointer to a single int[2].
      c = &a;

      c[0] = 7;
      assert(a[0] == 7); // OK, as expected

      c[1] = 42;
      assert(b[0] == 42); // do we really want this semantics?

A manifestation of undefined behavior.
 But "c[1] = 42" is equivalent to "(*(c+1)) = 42", which might not be
 obvious. In this case it ends writing to b[0].

It seems to be so but it is not defined to work that way. Ali
Apr 01 2013
prev sibling next sibling parent =?UTF-8?B?Ikx1w61z?= Marques" <luismarques gmail.com> writes:
On Tuesday, 2 April 2013 at 04:48:54 UTC, Steven Schveighoffer 
wrote:
 HOWEVER, there is one horrible caveat.  You must have assigned 
 an element at least once in order to alias:

Thanks Steve, I had already looked into that, but then got dense and I was treating the AA as having value semantics. I don't need the pointer. Is there a way to ensure the AA is initialized as not null, besides adding and removing an element? (I couldn't use a literal) Is the null initializer a consequence of the current opaque implementation, or just of the reference semantics? (I saw on the wiki that there was a desire to use a less opaque implementation. I think the AA ABI should be documented, like the other arrays) Slightly related, it doesn't seem very reasonable to me that the get method of AAs is not safe: safe: void main() { int[string] x; x.get("b", 0); } Error: safe function 'D main' cannot call system function 'object.AssociativeArray!(string, int).AssociativeArray.get'
Apr 01 2013
prev sibling parent "Steven Schveighoffer" <schveiguy yahoo.com> writes:
On Tue, 02 Apr 2013 01:59:13 -0400, Lu=C3=ADs Marques <luismarques gmail=
.com>  =

wrote:

 On Tuesday, 2 April 2013 at 04:48:54 UTC, Steven Schveighoffer wrote:
 HOWEVER, there is one horrible caveat.  You must have assigned an  =


 element at least once in order to alias:

Thanks Steve, I had already looked into that, but then got dense and I=

 was treating the AA as having value semantics. I don't need the pointe=

 Is there a way to ensure the AA is initialized as not null, besides  =

 adding and removing an element? (I couldn't use a literal)

Not sure. Looking... can't find anything. So no. There really should be.
 Is the null initializer a consequence of the current opaque  =

 implementation, or just of the reference semantics? (I saw on the wiki=

 that there was a desire to use a less opaque implementation. I think t=

 AA ABI should be documented, like the other arrays)

The AA ABI is defined by druntime in object.di. AA's are currently a = hybrid between a compiler-magic type and a template. The plan is to mak= e = it completely a template, that is, the compiler simply always treats T[U= ] = as AssociativeArray!(T, U). The null initializer is a result of D's policy on struct initialization.= = Default constructors are not allowed on structs, they must be able to be= = initialized with static data when declared without a constructor.
 Slightly related, it doesn't seem very reasonable to me that the get  =

 method of AAs is not safe:

  safe:

 void main()
 {
      int[string] x;
      x.get("b", 0);
 }

 Error: safe function 'D main' cannot call system function  =

 'object.AssociativeArray!(string, int).AssociativeArray.get'

Someone (can't remember who) went through a lot of effort to try and = re-implement AAs as object.AssociativeArray and ran into a lot of proble= ms = with things like safe and pure. It really should be safe, but I don't= = know if there was a specific reason why it wasn't tagged that way. -Steve
Apr 02 2013