Re: static array of pointers to dynamic arrays of ints problem...

2018-04-23 Thread Steven Schveighoffer via Digitalmars-d-learn

On 4/22/18 2:00 AM, WhatMeForget wrote:

Surely a stupid mistake on my part, but why is the first array repeated?


In addition to what Neia said, you shouldn't use pointers to dynamic 
arrays. Such things are really hard to allocate on the heap, since new 
int[] just makes an array, not a pointer to an array. You're way more 
likely to accidentally store pointers to stack variables (as demonstrated).


The only way 2 ways I know of to do it are to a) allocate a 
multi-dimensional array, and take it's pointer (e.g. (new int[][1]).ptr) 
or b) create a dummy struct with an array in it, and new that:


Struct Dummy { int[] array; }

auto p = new Dummy;
auto ptr = 

Just use int[][2] a, you will be better off.

-Steve


Re: static array of pointers to dynamic arrays of ints problem...

2018-04-22 Thread Neia Neutuladh via Digitalmars-d-learn

On Sunday, 22 April 2018 at 06:00:15 UTC, WhatMeForget wrote:

foreach(i, elem; a)
{
int[] temp = new int[](5);
..
a[i] = 
}


You're taking the address of a local variable and persisting it 
beyond the variable's scope. This is not safe in general; 
compilers regularly reuse spaces on the stack. DMD specifically 
tends to do this reliably with foreach loop bodies.


You see the same thing in C:

#include 

int main(int argc, char** argv)
{
int* p[2];
for (int i = 0; i < 2; i++)
{
int f = i;
p[i] = 
}
printf("p[0] = %x, *p[0] = %d\n", p[0], *p[0]);
printf("p[1] = %x, *p[1] = %d\n", p[1], *p[1]);
return 0;
}

Which prints something like:

p[0] = d9b69428, *p[0] = 1
p[1] = d9b69428, *p[1] = 1


static array of pointers to dynamic arrays of ints problem...

2018-04-22 Thread WhatMeForget via Digitalmars-d-learn
Surely a stupid mistake on my part, but why is the first array 
repeated?



import std.stdio;

void main()
{
int[]*[2] a;  // a static arrray holding pointers to dynamic 
arrays


static int unique = 0;

foreach(i, elem; a)
{
int[] temp = new int[](5);
foreach(ref element; temp)
{
element = unique;
unique++;
}
writeln("temp = ", temp);
a[i] = 
}

foreach(i, elem; a)
{
writeln(a[i].length);
writeln("[", i, "][]", *a[i]);
}
}

temp = [0, 1, 2, 3, 4]
temp = [5, 6, 7, 8, 9]
5
[0][][5, 6, 7, 8, 9]
5
[1][][5, 6, 7, 8, 9]


Re: Pointers to Dynamic Arrays

2015-08-17 Thread Adam D. Ruppe via Digitalmars-d-learn

On Monday, 17 August 2015 at 13:27:19 UTC, Brandon Ragland wrote:
If that is true, than passing it as _char[] file_ makes the 
most sense to me. A pointer copy doesn't hurt as bad as an 
array copy, of say, 100Kibibytes...


Right.

Knowing this helps to explain a lot btw:

char[] foo;

void func(char[] arg) {

}

func(foo);


In that scenario, foo's data is not copied, just a pointer to it 
is. Very fast operation.


arg[0] = 'a';

Since it is a pointer, writing to the arg will also write to foo.

BUT:

arg = a new thing;

This will NOT be seen outside. It wrote a new pointer to the 
local variable arg's pointer, so now arg and foo point to 
different data.


Similarly:

arg ~= 'a';

will not be seen outside. The pointer might change which is not 
seen outside, and the length will change, which is also not seen.



So char[] arg in D is similar to char* arg_ptr, size_t length_ptr 
in C - changing them inside the function just modifies local 
variables, not the outer variable. Writing *through the pointer 
will be seen outside though since they talk to the same data.





Similarly, slicing in D is just a pointer assignment:

char[] a = b[3 .. 4];

That's like in C:

a.ptr = b.ptr + 3;
a.length = 4-3;


Just basic arithmetic and assignment, no data copy going on.






This is all talking about T[] slices. Static arrays, in the form 
of T[constant], are different:




ubyte[4] static_data;

void slice_test(ubyte[] slice) {}

void static_test(ubyte[4] copy) {}


slice_test(static_data[]); // passes a pointer to the data

static_test(static_data); // passes a copy.




So T[] is always talking about pointer+length, but T[n] is always 
talking about a block of memory which is copied around to other 
T[n].


Putting the [] at the end of it, like I did with slice_test, 
fetches a pointer instead of copying. It is how you convert a 
static memory chunk to a pointer.




There's a few more things but you should understand it now, apply 
the low level principles to it and it all should make sense.


More reading:
http://dlang.org/d-array-article.html
http://dlang.org/arrays.html


Re: Pointers to Dynamic Arrays

2015-08-17 Thread Brandon Ragland via Digitalmars-d-learn

On Monday, 17 August 2015 at 03:07:26 UTC, Adam D. Ruppe wrote:
On Monday, 17 August 2015 at 02:45:22 UTC, Brandon Ragland 
wrote:

[...]


Short answer: pointers to slices are usually a mistake, you 
probably don't actually want it, but rather should be using a 
regular slice instead.



[...]


Here, for example, you've accidentally escaped slice land and 
are unto unchecked pointer arithmetic.


Since file is declared char[]* instead of char[], indexing it 
works C style: it at the index as an offset from the base 
char[].


In other words, it works more as if you wrote `char** file` in 
C. (still not identically, a D slice is different than a C 
char*, but same idea).


The above will only really work fine for index 0. Anything else 
would be a wild pointer. If this didn't crash on you, you just 
got kinda lucky with the index.


The append compiles because dereferencing a `char[]*` yields a 
`char[]`, which D can append normally.




[...]


This errors for the same reason the top one succeeded: what's 
pointed to by a char[]* is char[], not char. So you are trying 
to compare a string on the left hand side to an individual 
character on the right hand side.


In other words, what your error message told :)


[...]


char[] in D is like:

struct char_array {
size_t length;
char* ptr;
}

in C. Since there's already a pointer in there, you typically 
don't want the address of this struct, you just want to pass it 
right down by value and let the pointer be copied (it still 
points to the same actual data).


BTW you can access those .length and .ptr values in D:

char[] slice;
char* a = slice.ptr; // works

The only time you'd actually want a char[]* in D is if you need 
to write back to the original *variable* once you append or 
shrink it. (The contents are fine, they can be modified through 
the slice with no special effort.)



Bottom line again is char[] in D is like char* in C. So char[]* 
in D is more like char** in C.


Thanks Adam.

I keep getting myself confused with D, when I'm thinking in C 
land. Breaking it down like that is extremely helpful.


Going off what you're saying, this signature:

method(char[] file)

Would only copy the _pointer_, as this is similar to the C style 
struct you mentioned:


struct char_array {
size_t len;
char* index;
}

If that is true, than passing it as _char[] file_ makes the most 
sense to me. A pointer copy doesn't hurt as bad as an array copy, 
of say, 100Kibibytes...


-Brandon


Pointers to Dynamic Arrays

2015-08-16 Thread Brandon Ragland via Digitalmars-d-learn

Howdy,

Since Dynamic Arrays / Slices are a D feature, using pointers to 
these has me a bit confused...


Consider:

string c2s(int* pos, char[]* file, int l){
char[] s;
for(int i = 0; i  l; i++){
s ~= file[(*pos + i)];
}
return s.dup;
}

Now what is especially confusing about this, is that the above 
seems to works fine, while this does not:


if(file[(*pos + i)] == '}'){
*pos += i;
return;
}

This fails with this error:
Error: incompatible types for ((file[cast(ulong)(*pos + i)]) == 
('}')): 'char[]' and 'char'


Now what I do not understand, is if the above works, by appending 
come chars gathered from the dynamic array via pointer to me new 
dynamic array named s, and the below does not seem to work on 
comparison of two chars, what is really going on?


I can no longer assume that using the dynamic array pointer works 
anything like a standard pointer to an array, or a pointer to a 
dynamic array.


Is there something I'm missing?

Remember, that de-referencing a dynamic array was deprecated. So 
what I would normally have done: dynamic_array_pntr does not 
work any longer, and there is no new spec on what to do...


-Brandon


Re: Pointers to Dynamic Arrays

2015-08-16 Thread Freddy via Digitalmars-d-learn

On Monday, 17 August 2015 at 02:45:22 UTC, Brandon Ragland wrote:

if(file[(*pos + i)] == '}'){
*pos += i;
return;
}


That code doesn't do what you want it do. file is a ((char[])*) 
you are indexing the pointer(accessing invalid memory) and 
getting a char[].


Re: Pointers to Dynamic Arrays

2015-08-16 Thread Nicholas Wilson via Digitalmars-d-learn

On Monday, 17 August 2015 at 02:45:22 UTC, Brandon Ragland wrote:

Howdy,

Since Dynamic Arrays / Slices are a D feature, using pointers 
to these has me a bit confused...


Consider:



Now what is especially confusing about this, is that the above 
seems to works fine, while this does not:


if(file[(*pos + i)] == '}'){
*pos += i;
return;
}

This fails with this error:
Error: incompatible types for ((file[cast(ulong)(*pos + i)]) == 
('}')): 'char[]' and 'char'



This is wrong. what you want is (*file)[(*pos + i)] == '}'
file is a pointer. deref it you get a char array. index that you 
get a char.
Now what I do not understand, is if the above works, by 
appending come chars gathered from the dynamic array via 
pointer to me new dynamic array named s, and the below does 
not seem to work on comparison of two chars, what is really 
going on?


I can no longer assume that using the dynamic array pointer 
works anything like a standard pointer to an array,


It is. arr.ptr[n] is the same as arr[n] (modulo bounds checking)


or a pointer to a dynamic array.

Is there something I'm missing?

Remember, that de-referencing a dynamic array was deprecated. 
So what I would normally have done: dynamic_array_pntr does 
not work any longer, and there is no new spec on what to do...


-Brandon



string c2s(int* pos, char[]* file, int l){
char[] s;
for(int i = 0; i  l; i++){
s ~= file[(*pos + i)];
}
return s.dup;
}



would more idiomatically be written as
string c2s(int* pos, char[]* file, int k)
{
char* p = *file.ptr+*pos;
return  p[0 .. k].dup
}

or changing the signature
string c2s(char[] file, size_t offset,size_t length)
{
return file[offset .. offset + length].dup;
}


Re: Pointers to Dynamic Arrays

2015-08-16 Thread Adam D. Ruppe via Digitalmars-d-learn

On Monday, 17 August 2015 at 02:45:22 UTC, Brandon Ragland wrote:
Since Dynamic Arrays / Slices are a D feature, using pointers 
to these has me a bit confused...


Short answer: pointers to slices are usually a mistake, you 
probably don't actually want it, but rather should be using a 
regular slice instead.



string c2s(int* pos, char[]* file, int l){
char[] s;
for(int i = 0; i  l; i++){
s ~= file[(*pos + i)];


Here, for example, you've accidentally escaped slice land and are 
unto unchecked pointer arithmetic.


Since file is declared char[]* instead of char[], indexing it 
works C style: it at the index as an offset from the base char[].


In other words, it works more as if you wrote `char** file` in C. 
(still not identically, a D slice is different than a C char*, 
but same idea).


The above will only really work fine for index 0. Anything else 
would be a wild pointer. If this didn't crash on you, you just 
got kinda lucky with the index.


The append compiles because dereferencing a `char[]*` yields a 
`char[]`, which D can append normally.



Now what is especially confusing about this, is that the above 
seems to works fine, while this does not:


if(file[(*pos + i)] == '}'){


This errors for the same reason the top one succeeded: what's 
pointed to by a char[]* is char[], not char. So you are trying to 
compare a string on the left hand side to an individual character 
on the right hand side.


In other words, what your error message told :)

I can no longer assume that using the dynamic array pointer 
works anything like a standard pointer to an array, or a 
pointer to a dynamic array.


char[] in D is like:

struct char_array {
size_t length;
char* ptr;
}

in C. Since there's already a pointer in there, you typically 
don't want the address of this struct, you just want to pass it 
right down by value and let the pointer be copied (it still 
points to the same actual data).


BTW you can access those .length and .ptr values in D:

char[] slice;
char* a = slice.ptr; // works

The only time you'd actually want a char[]* in D is if you need 
to write back to the original *variable* once you append or 
shrink it. (The contents are fine, they can be modified through 
the slice with no special effort.)



Bottom line again is char[] in D is like char* in C. So char[]* 
in D is more like char** in C.