0

If I have a big 1d array declared like this

1darray = malloc(N*sizeof(double))

and I have another structure declared like this

for j:A

  2dstructure[j] = malloc(C[j]*sizeof(double*))     

  for i:B

    2dstructure[j][i] = malloc(D*sizeof(double))

  end
end

And the size of A*B = N, that means sizeof(1darray) == sizeof(2dstructure)

Is there a way I can copy what I have in 1d array to the 2d structure without using a loop?

Atirag
  • 1,660
  • 7
  • 32
  • 60

3 Answers3

3

Yes, you can map your 2D indices to a linear 1D index thus:

int idx = j*B + i;

At that point, 1darray[idx] is equivalent to 2dstructure[j][i].

Oliver Charlesworth
  • 267,707
  • 33
  • 569
  • 680
  • sorry I didn't explain myself very well. What I want is to copy what I have in the 1d array into the 2d structure without using loops. – Atirag May 29 '13 at 18:16
  • 5
    @Atirag: No, because your code above doesn't really create a 2D structure, it creates an array of pointers to arrays. The corresponding memory will not be contiguous. – Oliver Charlesworth May 29 '13 at 18:17
2

Assuming you have an 1D N-element array initialised like this:

double *onedarray = malloc(N*sizeof(double));

And you want to create a 2D AxB element array, where A*B = N. You could create the data for the 2D array as a contiguous block of memory like this:

double *twoddata = malloc(A*B*sizeof(double));

And then create the structure separately, like this:

double **twodstructure = malloc(A*sizeof(double*));
for (int i = 0; i < A; i++)
  twodstructure[i] = &twoddata[i*B];

Then copying from the 1D array to the 2D array, is a simple memcpy:

memcpy(twoddata, onedarray, N*sizeof(double));

And you can access your 2D array in a structured manner with code like this:

for (int i = 0; i < A; i++)
  for (int j = 0; j < B; j++)
    printf("%f\n", twodstructure[i][j]);
James Holderness
  • 22,721
  • 2
  • 40
  • 52
  • 1
    In C, don't cast the return of `malloc`: http://stackoverflow.com/questions/605845/do-i-cast-the-result-of-malloc – Jens Gustedt May 29 '13 at 19:03
1

With your allocation pattern, you can't do a simple copy because of the multiple allocations in the second loop. It depends on what you're really after. You can arrange things so that you do just one allocation of a set of pointers — by setting up pointers into your current 1D array so that you can access it as a 2D array. Alternatively, you can create a copy of your 1D array and then set up the pointers (2 allocations, 1 copy, 1 initialization loop). Since the only issue is whether to copy the original allocation, the main answer will work on the original data.

You have:

int N, A, B;
A = ...;
B = ...;
N = A * B;

double *a_1d = malloc(N * sizeof(double));

...check and load a_1d...

Now you can create a 2D 'array' by:

double **a_2d = malloc(A * sizeof(double *));

...check that allocation succeeded...

for (int i = 0; i < A; i++)
    a_2d[i] = &a_1d[i * B];

With this initialization done, you can now use:

for (int i = 0; i < A; i++)
    for (int j = 0; j < B; j++)
        a_2d[i][j] = ...;

If you really need to duplicate the original a_1d array, you'd add:

double *a_1d_copy = malloc(N * sizeof(double));
...check that the allocation succeeded...
memmove(a_1d_copy, a_1d, N * sizeof(double));

and then you can reference a_1d_copy instead of a_1d in setting up a_2d.

Remember that when it comes time to free things, you need to release both a_1d and a_2d (and a_2d_copy if you're using that).

Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278