3

I have created a 2 d array which reads as follows

     int i,j,lx,ly;// lx,ly are the row and column respectively
     double** a;

     a=(double**) malloc((lx+2)*sizeof(double));

     a[0]= (double*) malloc((lx+2)*(ly+2)* sizeof(double));

     assert(a[0]); 

     for(i=1;i<lx+2;i++)
     {
       a[i]=a[i-1]+i*(ly+2);
     }

// I allocate a value of 0 to all the elements in this array as below

    for(i=0;i<(lx+2)*(ly+2);i++)
    {
      a[i]=0;
    } 

// I print out all my elements below

      for(i=0;i<(lx+2)*(ly+2);i++)
      {
         printf("position %d values %d\n",i,a[i]);
      } 

// When I see the output , it shows me a junk value at one particular position 13. I am unable to figure that out .. ALso kindly tell me how to access rows and columns like Eg to acces 7 th column row 0 and 5th row 6 th column in terms of lx, ly as shown in my code

Pascal Cuoq
  • 79,187
  • 7
  • 161
  • 281
  • What is this? a[0]= (double*) malloc((lx+2)*(ly+2)* sizeof(double)); That's not how you initialize the second dimension of an array. – Dark Falcon Feb 14 '10 at 01:14
  • I'm tagging this `c`, change it if I'm wrong. This site is for all programming activities, most readers do not use C at all here. Help people who can help you find your question with meaningful tags. – Pascal Cuoq Feb 14 '10 at 01:18
  • This seems suspiciously like homework. Can you explain lx and ly? They don't seem to be initialized. – John M. P. Knox Feb 14 '10 at 01:45
  • Hi John, This is very much a Homework, but a part of that. I need to learn how to work with contiguous 2 d arrays to finish the whole assignment. – srinivasavaradan Feb 14 '10 at 01:57

4 Answers4

5

Your approach is definitely heading in the right general direction.

I think this:

a=(double**) malloc((lx+2)*sizeof(double));

would normally be:

a = malloc(lx * sizeof(double *));

And then without the contiguity requirement, this:

a[0]= (double*) malloc((lx+2)*(ly+2)* sizeof(double));

in most programs would look like:

a[0] = malloc(ly * sizeof(double));

And finally, that last line needs to be in a loop that assigns each a[i] with it's own malloc'ed space.

However, that won't create contiguous memory. To do that you will need to do that big allocation and then divide it up for the row vector. So, instead of the second malloc in a loop, perhaps something like:

double *t = malloc(lx * ly * sizeof(double));
for (i = 0; i < lx; ++i)
    a[i] = t + i * ly;

Putting it all together:

#include <stdio.h>
#include <stdlib.h>

void arrayDemo(int lx, int ly)
{
  double **a;
  int i, j;

  a = malloc(lx * sizeof(double *));
  double *t = malloc(lx * ly * sizeof(double));
  for(i = 0; i < lx; ++i)
    a[i] = t + i * ly;

  for(i = 0; i < lx; ++i)
    for(j = 0; j < ly; ++j)
      a[i][j] = i*100 + j;
  for(i = 0; i < lx; ++i) {
    for(j = 0; j < ly; ++j)
      printf(" %4.0f", a[i][j]);
    printf("\n");
  }
}

int main(int ac, char **av)
{
  arrayDemo(atoi(av[1]), atoi(av[2]));
  return 0;
}

$ cc -Wall all.c
$ ./a.out 4 7
    0    1    2    3    4    5    6
  100  101  102  103  104  105  106
  200  201  202  203  204  205  206
  300  301  302  303  304  305  306
DigitalRoss
  • 143,651
  • 25
  • 248
  • 329
  • HI Using 2 malloc's would not give me a contiguous memory right ? What I am expecting is a contiguous memory... Hence Is there any mechanism to do that? – srinivasavaradan Feb 14 '10 at 01:32
  • Right, sometimes SO rewards incremental answers, sorry for the delay. :-) The final line works because `i * lx` is evaluated first and then becomes *pointer + int* which causes the *int* to be scaled by the object size. – DigitalRoss Feb 14 '10 at 01:37
  • Hi, The second code looks cool. Could you please elaborate more? This is what I understand... I just make a[i] point to each row in the array correct? Now what do I need to do to access the same , to fill values in both rows and columns. Thanks in advance for the quick reply. – srinivasavaradan Feb 14 '10 at 01:47
  • Also what will happen If I do something like this? a=(double*) malloc((lx+2)*(ly+2)*sizeof(double)); for(i=0;i<(lx+2)*(ly+2);i++) { a[i]=0; } – srinivasavaradan Feb 14 '10 at 01:49
  • Even with my last example you still need the first malloc which allocates a vector of pointers to the original rows. So, you then access the array with `a[i][j]`. So maybe `for(i=0; i – DigitalRoss Feb 14 '10 at 02:02
  • Thanks, But isn't * t a single dimensional array ? If that is so then How can I use a[i][j]? My understanding is that we can use only one "[]" for a single dimensional array and 2 "[][]" for a 2 dimensional array – srinivasavaradan Feb 14 '10 at 02:15
  • At first, yes, `t` has one dimension, but we take where each row *would have started* had `t` been statically declared, and we assign that row origin to right element of the pointer vector `a[]`. It's not the same thing as a 2D array, it's a pointer vector, but it's used the same way in the later source code and it can be faster as the compiler doesn't need to multiply the row subscript by the row length. Try the example, it works. :-) – DigitalRoss Feb 14 '10 at 02:23
  • Hi Thanks a Lot. Ross how can I contact you other than stack overflow? Can I in the first place? and If I can then kindly let me know how? My mail id is savinirs.varadan@gmail.com – srinivasavaradan Feb 14 '10 at 02:34
2

This code allocates a 10 by 5 contiguous block of memory, initializes it with incrementing doubles, and then prints the values indexed by x and y:

#include "2d.h"

int main(void){

    unsigned int x,y;
    const unsigned int width = 10;
    const unsigned int height = 5;

    //we need an index into the x of the array
    double * index[width];

    //need the memory to store the doubles
    unsigned int memorySizeInDoubles = width * height;
    double * memory = malloc(memorySizeInDoubles * sizeof(double));

    //initialize the memory with incrementing values
    for(x = 0; x < memorySizeInDoubles; ++x){
        memory[x] = (double) x;
    }

    //initialize the index into the memory
    for(x = 0; x < width; ++x){
        index[x] = memory + height * x;
    }

    //print out how we did
    for(x = 0; x < width; ++x){
        for(y = 0; y < height; ++y){
           printf("[%u, %u]: Value = %f\n", x, y, index[x][y]);
        }
    }

    free(memory);

    return 0;
}

The 2d.h file should contain these lines:

#include <stdio.h>
#include <stdlib.h>

int main(void);

Note: The memory created is only contiguous for some definitions. The memory is logically contiguous, but not necessarily physically contiguous. If this memory is for a device driver for instance, malloc won't work.

John M. P. Knox
  • 713
  • 4
  • 11
0

Either you create a single dimension array

double my_array = malloc(sizeof(double) * size_x * sizeof(double) * size_y);

which you will access by

(get position x=28, y=12)

my_array[12 * size_x + 28];

or you create a 2d array like you do, but you access it with

double **my_array = (double**) malloc(15 * sizeof(double));

for(int i = 0 ; i < 25; i++)
   {
   my_array[i] = (double*) malloc(30 * sizeof(double));
   for (int j = 0 ; j < 12; j++)
      {
      my_array[i][j] = 1.2;
      }
   }

double my_double = my_array[12][28];
Eric
  • 19,525
  • 19
  • 84
  • 147
0

In C, to have one chunk of contiguous memory, you need one malloc(), or have a statically allocated array. Since you want dynamic memory, you will need malloc(). Since you need everything to be contiguous, you will need only one call to it.

Now, what should the call look like? If I understood you correctly, you need lx times ly values, each with size sizeof(double), so you need lx*ly*sizeof(double) bytes to be allocated.

Digression: I prefer writing my malloc() calls as follows:

#include <stdlib.h> /* for malloc's prototype */
T *pt; /* for any type T */
size_t n; /* need n objects of type T */

pt = malloc(n * sizeof *pt);

Using sizeof with sizeof *pt instead of sizeof(T) offers an advantage that if the type of pt changes, you don't need to change the malloc() call. Not casting the result of malloc() is nice because then the whole malloc() call is type-agnostic, and is easier to type and read. Be sure to #include <stdlib.h> though.

So, to allocate space for n doubles, you can do:

double *pd = malloc(n * sizeof *pd);
if (pd != NULL) {
    /* malloc succeeded */
} else {
    /* malloc failed */
}

Now, after allocating memory, you need to be able to index it. Let's say you have lx == 2 and ly == 3. Your memory looks like:

    +---+---+---+---+---+---+
pd: | 0 | 1 | 2 | 3 | 4 | 5 |
    +---+---+---+---+---+---+

pd[0], pd[1] and pd[2] are the double values corresponding to the first row, pd[3] to pd[6] are the double values corresponding to the second row. You should be able to generalize this observation to translate a given x,y index pair to one number that indexes into your pd array properly.

Alok Singhal
  • 93,253
  • 21
  • 125
  • 158