Sorry, this became a 3-fold question regarding arrays
I think (dynamic) arrays are truly powerful in D, but the following has been bothering me for a while:
In C++ I could easily allocate an array with designated values, but in D I haven't found a way to do so. Surely the following is no problem:
int[] a = new int[N];
a[] = a0;
But it looks inefficient, since line one will initialize with 0, and like 2 with a0. Could something similar to the following be done in D?
int[] a = new int(a0)[N]; // illegal
Another efficiency matter I have when using stride in std.range:
import std.stdio;
import std.range;
struct S
{
int x;
this(this)
{
writeln("copy ", x);
}
}
void f(S[] s)
{
}
int main()
{
S[] s = new S[10];
foreach (i, ref v; s)
{
v.x = i;
}
f(stride(s, 3)); // error
return 0;
}
Surely I was naive thinking I could simply use stride to create a new array without copying it's elements? There is no way to do so in D, right?
So I went and simulated as if the array was as stride would return, and implemented f as:
f(s, 3);
void f(S[] s, uint stride)
{
ref S get(uint i)
{
assert (i * stride < s.length);
return s[i * stride];
}
for (uint x ... )
{
get(x) = ...;
}
}
Would there be a way to instead write get(x) using the index operator get[x]? This way I could statically mixin / include the striding get function and keep the rest of the function similar. I'd be interested in the approach taken, since a local struct is not allowed to access function scope variables (why not?).
But it looks inefficient, since line one will initialize with 0, and like 2 with a0. Could something similar to the following be done in D?
Use std.array.uninitializedArray
S[] s = uninitializedArray!(S[])(N);
s[] = a0;
Surely I was naive thinking I could simply use stride to create a new array without copying it's elements? There is no way to do so in D, right?
Your function f has an S[] as an argument, which is different from what stride returns. The D way to solve this is to make your f function accept any range by making it a template:
void f(Range)(Range s)
{
foreach (item; s)
// use item
}
S[] s = new S[10];
f(s); // works
f(stride(s, 3)); // works too
Alternatively you can copy the array:
f(array(stride(s, 3)));
But you probably want to avoid copying the entire array if it is large.
Would there be a way to instead write get(x) using the index operator get[x]? This way I could statically mixin / include the striding get function and keep the rest of the function similar. I'd be interested in the approach taken, since a local struct is not allowed to access function scope variables (why not?).
You can overload the indexing operator in your own struct.
struct StrideArray
{
this(S[] s, uint stride) { m_array = s; m_stride = stride; }
S opIndex(size_t i) { return s[i * m_stride]; }
void opIndexAssign(size_t i, S value) { s[i * m_stride] = value; }
private S[] m_array;
private uint m_stride;
}
This is (kind of) the way the actual stride function works. I'd recommend reading up on Ranges.
you can duplicate (create a copy of) an array with .dup (this will also work with slices) or you can set the elements with the array initializer
int[] a=a0.dup;
int[] b=[e1,e2,e3];
you can make the f generic (stride() returns a struct that you can iterate over, not an array)
void f(Z)(Z s)if(isInputRange!Z){
foreach(elem;s){
//...
}
}
remember that arrays are essentially structs with a pointer field to some memory block and a size field
Related
I am having a bunch of problems with pointers and dynamic arrays here.
I have a function that I call, that does a bunch a stuff, like removing an ellement from the dynamic array , which leads me to reallocating memory to one of those dynamic arrays. The problem is I call functions within functions, and I can't return all my values properly to the Main.
Since I can't return 2 values, how can I do this?
structure1* register(structure1 *registerArray,structure2 *waitingList, int counter){
//Bunch of code in here
registerArray = realloc(inspecao, (counter)+1);
waitingList = eliminate(waitingList, 5, counter); //Doesn't matter what it does really
return registerArray;
}
structure1* eliminate(structure1 *arrayToEliminateFrom, int positionToEliminate, int *counter){
//The code for this doesn't matter
//All I do is eliminate an ellement and reallocate it
arrayToEliminateFrom = realloc(arrayToEliminateFrom, (*counter-1)*sizeof(structure1))
return arrayToEliminateFrom;
}
As you can see , I don't know how to return the pointer to the waitingList dynamic array to the Main. How can I do this?
I have searched everywhere.
Help
Okay, here are two ways to do it.
The first is, based upon your comment, what you think your instructor would want:
void
xregister(structure1 **registerArray, int *arrayCount,
structure1 **waitingList, int *waitCount)
{
// Bunch of code in here
*arrayCount += 1;
*registerArray = realloc(inspecao, *arrayCount * sizeof(structure1));
// Doesn't matter what it does really
eliminate(waitingList, 5, waitCount)
}
void
eliminate(structure1 **arrayToEliminateFrom, int positionToEliminate,
int *count)
{
// The code for this doesn't matter
*count -= 1;
// All I do is eliminate an ellement and reallocate it
*arrayToEliminateFrom = realloc(*arrayToEliminateFrom,
*count * sizeof(structure1))
}
Here is what Roberto and I were suggesting. Actually, mine's a general variable length array approach that can be fully generalized with some slight field changes. In a way, since you're already using a struct, I can't see why your instructor would object to this as it's a standard way to do it. Less cumbersome and cleaner.
struct vector {
int vec_count;
structure1 *vec_base;
};
void
xregister(vector *registerArray,vector *waitingList)
{
// Bunch of code in here
registerArray->vec_count += 1;
registerArray->vec_base = realloc(registerArray->vec_base,
registerArray->vec_count * sizeof(structure1));
// Doesn't matter what it does really
eliminate(waitingList, 5)
}
void
eliminate(vector *arrayToEliminateFrom, int positionToEliminate)
{
// The code for this doesn't matter
arrayToEliminateFrom->vec_count -= 1;
// All I do is eliminate an ellement and reallocate it
arrayToEliminateFrom->vec_base = realloc(arrayToEliminateFrom->vec_base,
arrayToEliminateFrom->vec_count * sizeof(structure1))
}
Here's an even more compact way:
struct vector {
int vec_count;
structure1 *vec_base;
};
void
vecgrow(vector *vec,int inc)
{
vec->vec_count += inc;
vec->vec_base = realloc(vec->vec_base,vec->vec_count * sizeof(structure1));
}
void
xregister(vector *registerArray,vector *waitingList)
{
// Bunch of code in here
vecgrow(registerArray,1);
// Doesn't matter what it does really
eliminate(waitingList, 5)
}
void
eliminate(vector *arrayToEliminateFrom, int positionToEliminate)
{
// The code for this doesn't matter
vecgrow(arrayToEliminateFrom,-1);
}
you should try to do an higher structure that contains both pointers and pass and return that structure beetween your functions, because function can return only one object/structure, but your structure/object can contain more objects/structures
I am in the process of designing some classes for dynamic arrays (something like a std::vector). The reason I don't want to use std::vector is because my C++ programs are often used as a library called from C/C++/Fortran/Delphi and therefore takes arrays input as a pointer. For security reasons, a std::vector can't steal a pointer at construction time. My Array1D can work as a std::vector but can also be constructed with a pointer. Unfortunately Visual Studio 2013 seems to be worried about my design. Before presenting the problem, I need to explain this design.
Here is the layout of my class
template <typename T>
class Array1D {
private:
T* data_;
T* size_; // No stored as an int for optimisation purposes
bool owner_;
public:
Array1D(int n) {
data_ = new T[n];
size_ = data_ + n;
owner_ = true;
}
Array1D(T* data, int n) {
data_ = data;
size_ = data + n;
owner_ = false;
}
...
};
Most of the time, it works as a std::vector and owner_ is set to true. One can also construct an Array1D from a pointer, and this time owner_ is set to false. In this case, some operations such as resizing are not allowed (through an assert). Copy constructor and assignment for the array A are designed as:
Array1D(const Array1D& B) : Deep copy of B into A. After construction, A owns its memory.
Array1D(Array1D&& B) : Move operation in all cases. After construction, the ownership status of A is the same as B.
operator=(const Array1D& B) : Deep copy of B into A. If A does not owns its memory, an assert is there to check that A and B have the same size. The assignment does not change the ownership status of A.
operator=(Array1D&& B) : Move operation if A and B owns their memory. Otherwise, we do a deep copy, and the size are checked with an assert if A does not own its memory. The assignment does not change the ownership status of A.
I have applied the same idea to my 2 dimensional array whose elements are stored in row-major order
template <typename T>
class Array2D {
private:
T* data_;
T* size_[2];
bool owner_;
public:
Array2D(int n, int p) {
data_ = new T[n];
size_[0] = data_ + n;
size_[1] = data_ + p;
owner_ = true;
}
Array1D(T* data, int n, int p) {
data_ = data;
size_[0] = data + n;
size_[1] = data + p;
owner_ = false;
}
...
Array1D<T> operator()(int i) {
Array1D<T> row(data_ + i * nb_columns(), nb_columns());
return row;
}
...
int nb_columns() const {
return static_cast<int>(size_[1] - data_);
}
};
The Array1D returned by operator()(int i) does not own its memory and contains a pointer to the ith-row owned by the Array2D object. Is is useful in the following kind of code
sort(Array1D<T>& A); // A function that sorts array in place
Array2D<double> matrix(5, 100); // Construct an array of 5 rows and 100 columns
... // Fill the array
sort(matrix(3)) // Sort the 4th row
Those "temporary views" for rows of an 2 dimensional arrays are quite useful but I prefer to limit them to temporary objects to limit aliasing.
Unfortunately, using Visual Studio 2013, I get the following warning from the IDE for the line sort(matrix(3)): "Options for binding r-value to l-value reference is non-standard Microsoft C++ extension". I understand that matrix(3) is an object that lives temporarly and modifying it through a sort looks strange. But, as it is a "view", modifying it modifies the memory owned by matrix and is useful.
So my questions are the following:
Is what I am doing valid C++? (modifying a temporary value)
Is there a flaw in this design?
PS: The full code is available on Github.
Is what I am doing valid C++? (modifying a temporary value)
It's not. Non-const lvalue references cannot bind to temporary objects:
http://herbsutter.com/2008/01/01/gotw-88-a-candidate-for-the-most-important-const/
Is there a flaw in this design?
You are modifying the contents that are wrapped in an object. Since you need to have an lvalue, it would simply be fixed by having an intermediate variable:
auto m_temp_lvalue = matrix(3); // get the 4th row
sort(m_temp_lvalue); // sort the 4th row
I hope it helps.
I have to go through each index of a 2d array and find what the neighbor values are and then update the index of the array based on that. My code below does all that but when I have to update the array it updates the existing array so the next index produces the incorrect output. I tried creating a new array but when I use the new array nothing is updated and it stays the same. This is what I have right now.
void ch(int **b, int w, int h)
{
int x,y,i,ct=0;
int **up;
up=malloc(sizeof(int *) * h);
for(i = 0; i<h; i++){
up[i]=malloc(sizeof(int)*w);
}
for (x=0;x<h;x++)
{
for(y=0;y<w;y++)
{
//...Computes Count Here(It Works)
//UPDATE BOARD - Does not update the board
if(b[x][y]==1 && ct<2)
{
up[x][y]=0;
}
else if(b[x][y]==1 && (ct==2 || ct==3))
{
up[x][y]=1;
}
else if(b[x][y]==1 && ct>3)
{
up[x][y]=0;
}
else if(b[x][y]==0 && ct==3)
{
up[x][y]=1;
}
ct=0;
}
}
b=up;
}
I tried updating the 2d array b by doing the changes on itself and it changes the array but it's not the output I am looking for. It changes the output at each iteration so output for other indexes changes but I want it so that another array keeps track of the output so that it does not update the b at every iteration and gives a correct out. What am I doing wrong that is not letting me update the up? What's the best approach to solve this issue?
Make a copy of the original array and use that as a reference. Then you can update your original array directly.
void ch(int **b)
{
int **up = malloc(sizeof(*int)*h);
int i;
for (i = 0; i < w; i++)
{
up[i] = malloc(sizeof(int) * w);
memcpy(up[i], b[i], w * sizeof(int));
}
//
if (up[x][y] == 1)
b[x][y] = 0;
}
// free up
This may be easier to maintain, than having an additional level of indirection as in
void ch(int ***b)
{
int **up = *b;
// do everything else as you intended
// finalize with
*b = up;
// free up
}
Also when making the copy, you can increase the performance a bit by allocating the temporary copy as a linear array
int *up = malloc(sizeof(int) * w * h);
if (up[y * w + x] == 0)
b[y][x] = 1;
C pass arguments by value.
so you can do this way
int* pass(int *p){
//return new pointer; and later assign
}
or get address
void pass(int **p)
{
*p=//new pointer
}
For your situation it is better to modify the same array inside without allocating new
I cannot modify the same array
You can work on copy of array as suggested then update previous array from copy
Or just return that copied array as suggested by me
Worth a look:
C Faq question related on your issue
C Faq ways for allocating multidimensional array
At the end of your function, where you have b=up;, you set b to point to your new array but that only changes your function's copy (b) and not the copy in the calling function... so the caller still sees the original array.
However, since you're using an array of pointers to arrays, rather than actual 2D arrays, you can replace the contents of b (the int *'s to the arrays making up the additional dimension)... and that will avoid having to copy all of your new array's data into the original array.
So instead of:
b=up;
try:
for(i = 0; i < h; i++) {
free(b[i]);
b[i] = up[i];
}
free(up);
That way each row of the original array gets replaced with the corresponding row from the new one, by changing the pointers in the original array of rows.
This is only a good idea, however, if the rows of the original array were dynamically allocated like the ones in your new array were, and if there are no other pointers to the rows floating around (outside of the array of rows passed as b) that might still point to the old memory afterward.
I have an array, which is now static. This are the operations I do with it.
Firstly I create a two-dimensional array. Then I fill it in, using cycles. And then I send it to function, where there are also cycles which are used.
Here I 'd like to post some sample code, which is similar to mine.
bool picture[20][20]; //here's my array right now. Pretty ugly. Just for testing.
for (int y=0;y<Height;y++)
{
for (int x=0;x<Width;x++)
{
if (treshold<middle)
{
picture[x][y]=1;
}
else
{
picture[x][y]=0;
}
}
}
//Here's an example of filling an array
leftk = left(picture,widthk, heightk); //That's how I use a function
int left(int picture[200][200],int row,int col)
{
for (int x = 0; x <=row-1; x++)
{
for (int y = 0; y <=col-1 ;y++)
{
if (picture1[x][y]==1)
{
return x;
}
}
}
}
//And that's the function itself
So here I need to switch my array to a dynamic one. That's how I declare my dynamic array
bool** picture=new bool*[size];
for(int i = 0; i < size; ++i)
picture[i] = new bool[size];
//size is just a variable.
As for statically declared cycles, everything is very simple. Sending this array as a parameter to function.
I've already managed to create a dynamic array, it's simple. Then I fill it in with numbers. No problems here too. But I can't understand, how to send an array to function and moreover how to use it there.
Could you give me an exaple of modifying two-dimensional arrays in functions.
Sorry for such a newbie question. Hope someone will help.
By the way, class wrapping would be a bit confusing here, I think.
A function such as:
Process2DArray(int **pArray, int rowCount, int colCount)
Should suffice the needs assuming its a 2D array that is being operated on. Also, consider using std::vector<std::vector<int>> instead of a multidimensional array allocated manually. This approach will help prevent leaks. The second approach also lets you have jagged arrays.
The usual solution is to wrap the array in a class; C doesn't handle
arrays very well, and C++ doesn't have any real support for 2D arrays in
its library either. So you define either:
class Array2D
{
std::vector<double> myData;
int myColumnCount;
int myRowCound;
// ...
};
with accessors which convert the two indexes using i * myColumnCount +
j, or:
class Array2D
{
std::vector<std::vector<double> > myData;
// ...
};
with initialization logic ensure that all of the rows have the same
length. The first is generally simpler and easier to understand; if you
want to increase the number of columns, however, the second is
significantly easier.
You have several options:
an array of arrays. For example, for int would be int **a which should be able to hold n arrays new int *[n], then go with a for through them and initialized them a[i] = new int[elems_per_line]
a "packed" 1D array int *a = new int[n * elems_per_line], where element (i, j) - 0-based is actually a[i * elems_per_line + j].
you can refine point 1, and have the 2D matrix be "curly" - with lines of different lengths, but you'll need an array to hold each length.
Hope this helps.
I'm attempting to create a simple 2D array in C but apparently running into some memory trouble. My setup is simple enough and I can't tell what's wrong. I admit that my understanding of pointers is insufficient, but I still think this should be working. Can anyone see the flaw here?
typedef unsigned int DATUM;
DATUM **series_of_data;
void initialize_data()
{
*series_of_data = (DATUM *) malloc(1024 * sizeof(DATUM));
}
This causes my program to crash with a bus error when I run it.
series_of_data is actually not allocated.
You have various way to allocates a 2D array, either using the array of rows model whcih has bad cache coherency and thus has usually bad performances or to use the Iliffe vector adviced in Numerical recipes in C that consists in allocating one huge h*w memory block and a side pointer array which contains the beginning of your rows (or columns) :
DATUM** alloc_array( int h, int w )
{
int i;
DATUM** m = (DATUM**)malloc(h*sizeof(DATUM*));
m[0] = (DATUM*)malloc(h*w*sizeof(DATUM));
for(i=1;i<h;i++) m[i] = m[i-1]+w;
return m;
}
void release_array(DATUM** m)
{
free( m[0] );
free( m);
}
int main()
{
int r,c;
DATUM** tab;
int width = 5;
int height = 3;
tab = alloc_array(height, width); /* column first */
for(r = 0;r<height;++r)
for(c = 0;c<width;++c)
tab[r][c] = (1+r+c);
for(r = 0;r<height;++r)
{
for(c = 0;c<width;++c)
{
printf("%d\t",tab[r][c]);
}
puts("");
}
release_array(tab);
}
Data are nicely packed in memory, so cache are happy and you keep the [][] access pattern.
As a matter of speed this is in +/-3% speed of the classical DATUM* + polynomial access method.
series_of_data is an invalid pointer - you don't assign it to anything. When you try to assign to its memory location (*series_of_data = ...), it's putting stuff in a random place, which is likely to not do what you want. You have to point series_of_data somewhere useful, e.g.
series_of_data = (DATUM **)malloc(16 * sizeof(DATUM *))
for an array with 16 slots for DATUM * pointers in it.
You haven't allocated the series_of_data pointer before you assign to *series_of_data.
For example, if series_of_data is intended to be an array then you would need to write something like this:
series_of_data = malloc(n*sizeof(DATUM*));
where n is the length of the series_of_data array.
Only after you have done this can you assign to *series_of_data.