www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Is this a bug?

reply "Andrey" <none none.no> writes:
Could anyone please explain to me, why do I have error message on 
this piece of code?

alias short Type1;
alias Type1[100]* Type2; // pointer to an array
struct Type3
{
	Type2 f
}
void foo()
{
    Type3* b;
    Type1  d;
    d = b.f[10]; // compilation error: cannot implicitly convert 
expression ((*b).f[10]) of type short[100] to short
    d = b.f[0][10]; // ok
}

Thank you in advance
Apr 28 2014
next sibling parent reply "John Colvin" <john.loughran.colvin gmail.com> writes:
On Monday, 28 April 2014 at 08:58:41 UTC, Andrey wrote:
 Could anyone please explain to me, why do I have error message 
 on this piece of code?

 alias short Type1;
 alias Type1[100]* Type2; // pointer to an array
 struct Type3
 {
 	Type2 f
 }
 void foo()
 {
    Type3* b;
    Type1  d;
    d = b.f[10]; // compilation error: cannot implicitly convert 
 expression ((*b).f[10]) of type short[100] to short
    d = b.f[0][10]; // ok
 }

 Thank you in advance
not a bug. b.f[10] is indexing the pointer to the array, not the array itself. b.f[0][10] is indexing the array (with the 10), but I would argue it is better to write *(b.f)[10] so as to be clear that f is not an array. What is the reason you are using a pointer to a struct containing a pointer to a static array? It's often not necessary to work like that.
Apr 28 2014
parent reply "Andrey" <none none.no> writes:
 not a bug.

 b.f[10] is indexing the pointer to the array, not the array 
 itself.

 b.f[0][10] is indexing the array (with the 10), but I would 
 argue it is better to write *(b.f)[10] so as to be clear that f 
 is not an array.
thank you, John. compiler said that '*(b.f)[10]' is deprecated, and I should write like this void foo() { Type3 b; Type1 d; d = *(b.f[10]).ptr; } which looks completely weird for me...
 What is the reason you are using a pointer to a struct 
 containing a pointer to a static array? It's often not 
 necessary to work like that.
it is just a sample... in real code the struct contains a lot of fields
Apr 28 2014
parent reply "John Colvin" <john.loughran.colvin gmail.com> writes:
On Monday, 28 April 2014 at 09:36:08 UTC, Andrey wrote:
 not a bug.

 b.f[10] is indexing the pointer to the array, not the array 
 itself.

 b.f[0][10] is indexing the array (with the 10), but I would 
 argue it is better to write *(b.f)[10] so as to be clear that 
 f is not an array.
thank you, John. compiler said that '*(b.f)[10]' is deprecated, and I should write like this void foo() { Type3 b; Type1 d; d = *(b.f[10]).ptr; }
struct T { int[10]* f; } void main() { int[10] test; T t = T(&test); T* b = &t; auto d = (*(b.f))[4]; //ugly but clear. d = b.f[0][4]; //prettier but less clear. } note the extra brackets on the ugly one, I forgot them before.
Apr 28 2014
next sibling parent reply "Andrey" <none none.no> writes:
bearophile, John, probably, my example was not clear...

The code below works.

alias short Type1;
alias Type1[100]* Type2; // if I take out '*' I will have to type 
it everywhere, because arrays in D2 always 'by value'

struct Type3
{
	Type1 key;
	int  flags;
         int  arrLen;
	Type2 f; // this struct can be *optionally* extended by the array
}

void foo(Type3* b)
{
    Type1  d;
    d = (*(*b).f)[10];
}

Thank you, I appreciate your help!!
Apr 28 2014
parent "bearophile" <bearophileHUGS lycos.com> writes:
Andrey:

 alias short Type1;
The "alias X Y;" syntax is going to be deprecated, so use "alias Y = X;" if your compiler already supports it.
 alias Type1[100]* Type2; // if I take out '*' I will have to 
 type it everywhere, because arrays in D2 always 'by value'
Adding the * everywhere could be a good thing, because it makes the code more explicit. Even in Linux kernel typedefs that just mask out a pointer are not appreciated a lot. D code that uses pointers to fixed size arrays is very uncommon in D, so adding a * there is not going to cause troubles.
 struct Type3
 {
 	Type1 key;
 	int  flags;
         int  arrLen;
 	Type2 f; // this struct can be *optionally* extended by the 
 array
 }
The common way to create a variable length struct in D is to use a zero length fixed size array (and no pointers): struct Type3 { Type1 key; int flags; int arrLen; Type1[0] f; } But if you don't mind the double indirection using a dynamic array is simpler: struct Type3 { Type1 key; int flags; Type1[] f; } Bye, bearophile
Apr 28 2014
prev sibling parent reply "Steven Schveighoffer" <schveiguy yahoo.com> writes:
On Mon, 28 Apr 2014 06:04:53 -0400, John Colvin  
<john.loughran.colvin gmail.com> wrote:

 On Monday, 28 April 2014 at 09:36:08 UTC, Andrey wrote:
 not a bug.

 b.f[10] is indexing the pointer to the array, not the array itself.

 b.f[0][10] is indexing the array (with the 10), but I would argue it  
 is better to write *(b.f)[10] so as to be clear that f is not an array.
thank you, John. compiler said that '*(b.f)[10]' is deprecated, and I should write like this void foo() { Type3 b; Type1 d; d = *(b.f[10]).ptr; }
struct T { int[10]* f; } void main() { int[10] test; T t = T(&test); T* b = &t; auto d = (*(b.f))[4]; //ugly but clear. d = b.f[0][4]; //prettier but less clear. } note the extra brackets on the ugly one, I forgot them before.
You don't need them. (*b.f)[4] works. '.' has precedence over '*'. -Steve
Apr 28 2014
next sibling parent "John Colvin" <john.loughran.colvin gmail.com> writes:
On Monday, 28 April 2014 at 14:02:33 UTC, Steven Schveighoffer 
wrote:
 On Mon, 28 Apr 2014 06:04:53 -0400, John Colvin 
 <john.loughran.colvin gmail.com> wrote:

 On Monday, 28 April 2014 at 09:36:08 UTC, Andrey wrote:
 not a bug.

 b.f[10] is indexing the pointer to the array, not the array 
 itself.

 b.f[0][10] is indexing the array (with the 10), but I would 
 argue it is better to write *(b.f)[10] so as to be clear 
 that f is not an array.
thank you, John. compiler said that '*(b.f)[10]' is deprecated, and I should write like this void foo() { Type3 b; Type1 d; d = *(b.f[10]).ptr; }
struct T { int[10]* f; } void main() { int[10] test; T t = T(&test); T* b = &t; auto d = (*(b.f))[4]; //ugly but clear. d = b.f[0][4]; //prettier but less clear. } note the extra brackets on the ugly one, I forgot them before.
You don't need them. (*b.f)[4] works. '.' has precedence over '*'. -Steve
The extra ones I referred to were the outer ones. Nonetheless, you're example is correct.
Apr 28 2014
prev sibling parent reply "Andrey" <none none.no> writes:
Ok, thanks a lot..

About dynamic arrays: I haven't found any information about 
internal representation of the D structures. E.g. do dynamic 
arrays have reference counter?

Nevermind, I'm gonna use Type2[0] syntax.
Apr 28 2014
next sibling parent reply "Andrey" <none none.no> writes:
btw,

short a,b,c;

a = b + c; //error: cannot implicitly convert expression of type 
'int' to 'short'

Guys!! Tell me that I have an old slutty version of the 
compiler...
Apr 29 2014
next sibling parent "Marc =?UTF-8?B?U2Now7x0eiI=?= <schuetzm gmx.net> writes:
On Tuesday, 29 April 2014 at 07:43:55 UTC, Andrey wrote:
 btw,

 short a,b,c;

 a = b + c; //error: cannot implicitly convert expression of 
 type 'int' to 'short'

 Guys!! Tell me that I have an old slutty version of the 
 compiler...
No, it's correct. `b + c` is not guaranteed to fit into `a`, therefore you have to cast it explicitly.
Apr 29 2014
prev sibling parent "Steven Schveighoffer" <schveiguy yahoo.com> writes:
On Tue, 29 Apr 2014 03:43:54 -0400, Andrey <none none.no> wrote:

 btw,

 short a,b,c;

 a = b + c; //error: cannot implicitly convert expression of type 'int'  
 to 'short'

 Guys!! Tell me that I have an old slutty version of the compiler...
No. It's due to integer promotion. All operations are done at the int level, so the expression b + c is actually an int. C allows this transgression because it's convenient. D makes you acknowledge that you are throwing away bits the compiler generated for you. Note, += does work: a = b; a += c; -Steve
Apr 29 2014
prev sibling parent reply "John Colvin" <john.loughran.colvin gmail.com> writes:
On Tuesday, 29 April 2014 at 06:13:52 UTC, Andrey wrote:
 Ok, thanks a lot..

 About dynamic arrays: I haven't found any information about 
 internal representation of the D structures. E.g. do dynamic 
 arrays have reference counter?

 Nevermind, I'm gonna use Type2[0] syntax.
D dynamic arrays (better referred to as slices) can be thought of as implmented like struct Array(T) { T* ptr; size_t length; } They do not track ownership or have any reference counting. If they've been allocated with "new" then the GC will take care of them once there are no remaining references to them.
Apr 29 2014
parent reply =?UTF-8?B?QWxpIMOHZWhyZWxp?= <acehreli yahoo.com> writes:
On 04/29/2014 01:36 AM, John Colvin wrote:

 D dynamic arrays (better referred to as slices) can be thought of as
 implmented like

 struct Array(T)
 {
      T* ptr;
      size_t length;
 }

 They do not track ownership or have any reference counting. If they've
 been allocated with "new" then the GC will take care of them once there
 are no remaining references to them.
That may be misleading because there is no need to allocate with an explicit new. For example, the slice below is owned by the GC as well: int[] foo() { int[] a; a ~= 42; // on memory owned by the GC return a; } Ali
Apr 29 2014
parent reply "Meta" <jared771 gmail.com> writes:
On Tuesday, 29 April 2014 at 16:52:27 UTC, Ali Çehreli wrote:
 That may be misleading because there is no need to allocate 
 with an explicit new. For example, the slice below is owned by 
 the GC as well:

 int[] foo()
 {
     int[] a;
     a ~= 42;    // on memory owned by the GC
     return a;
 }
I didn't realize this was possible... I figured it was equivalent to `null ~= 42` which I realize now is not correct, because a is not entirely a reference type. I'm not sure how I feel about this.
Apr 29 2014
next sibling parent =?UTF-8?B?QWxpIMOHZWhyZWxp?= <acehreli yahoo.com> writes:
On 04/29/2014 10:01 AM, Meta wrote:

 On Tuesday, 29 April 2014 at 16:52:27 UTC, Ali Çehreli wrote:
 That may be misleading because there is no need to allocate with an
 explicit new. For example, the slice below is owned by the GC as well:

 int[] foo()
 {
     int[] a;
a is an empty slice, ready for use.
     a ~= 42;    // on memory owned by the GC
Since there is no room for the new element, an area large enough for the new element and for some more is allocated from the GC. Now a is a handle to that one element. Adding the following line reveals that the memory that has just been allocate has room for more elements: writeln(a.capacity); // printed 3 for me
     return a;
 }
Yes, a's life ends but the slice that is being returned from the function is still alive. So, the GC does not free the memory yet. Ali
Apr 29 2014
prev sibling parent David Held <dmd wyntrmute.com> writes:
On 4/29/2014 10:01 AM, Meta wrote:
 On Tuesday, 29 April 2014 at 16:52:27 UTC, Ali Çehreli wrote:
 [...]
 int[] foo()
 {
     int[] a;
     a ~= 42;    // on memory owned by the GC
     return a;
 }
I didn't realize this was possible... I figured it was equivalent to `null ~= 42` which I realize now is not correct, because a is not entirely a reference type. I'm not sure how I feel about this.
Yeah, arrays and AAs sit in a no-man's-land between reference types and value types. :( I don't know that I've seen this precedent in any other language... Dave
Apr 29 2014
prev sibling parent "bearophile" <bearophileHUGS lycos.com> writes:
Andrey:

 Could anyone please explain to me, why do I have error message 
 on this piece of code?
In this thread you are doing some mistakes. This code seems OK: alias TData = short; alias TArray = TData[100]; struct MyStruct { TArray* arrPtr; } void main() { MyStruct* t3 = new MyStruct(new TArray[1].ptr); TData data0 = (*t3.arrPtr)[99]; } D is working as designed. (The only small problem is that you can't "new" a fixed size array, so I have had to allocate a dynamic array of TArray of length 1 and take the pointer to its first item. Another alternative solution is to wrap TArray into a struct.) Such kind of code is possible in D, but it should be quite uncommon in library code (and it can't be marked safe). There are usually simpler ways to do similar things in D. So perhaps there are ways to simplify your data structure (here I have kept the same structure you have used in the example). Bye, bearophile
Apr 28 2014