2

I need to create a two dimensional array. Presently I created it as int a[100][100]

but I need to allocate the memory dynamically using malloc in C language. I used the code

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

int main(void)
{     
    int n=6, m=5, i, j;
    int **a = malloc(n * sizeof(int *));
    for(i = 0; i < m; i++)
          a[i] = malloc(m * sizeof(int));

    for( i = 1; i <= n; i++ )
    {
        for( j = 1; j <= m; j++ )
        {
            scanf("%d %d",&a[i][j]);
        }
    }

    return 0;
}

but now while inputting the elements into the array it shows SEGMENTATION ERROR.

phuclv
  • 37,963
  • 15
  • 156
  • 475
Hridoy Dutta
  • 51
  • 1
  • 1
  • 5
  • 1
    You need to show the code that crashes. If you don't know which it is, then use a debugger (which you should be doing anyway). – Some programmer dude May 08 '14 at 06:29
  • 5
    Though it *might* be a problem with the allocation code, because you allocate `n` pointers first, but then you loop `m` times. Unless `m` is less than or equal to `m` you will have a problem there. – Some programmer dude May 08 '14 at 06:31
  • for my code n: the number of rows m: the number of columns...... – Hridoy Dutta May 08 '14 at 06:32
  • 1
    @JoachimPileborg: This is his error, because he is iterating over more elements than avaliable... – arc_lupus May 08 '14 at 06:33
  • 1
    As @JoachimPileborg mentioned, change `for(i = 0; i < m; i++)` to `for(i = 0; i < n; i++)` i.e. replace `m` by `n` – brokenfoot May 08 '14 at 06:35
  • 1
    @HridoyDutta It doesn't matter what you use the variables for, what's the matter is that you allocate `n` rows but then loop over the columns. If they are not the same you might have problems. – Some programmer dude May 08 '14 at 06:35
  • Oh, and in my second comment I of course mean "Unless `m` is less than or equal to **`n`**" – Some programmer dude May 08 '14 at 06:39
  • @Joachim Pileborg: Please check the edited code. I need to create the array a dynamically... – Hridoy Dutta May 08 '14 at 06:53
  • @HridoyDutta The basic idea is correct but **you are allocating the wrong number of rows** and you are also accessing out of bounds of what you did allocate. Please read Joachim Pileborg and brokenfoot's comments – M.M May 08 '14 at 06:57

5 Answers5

2

You say in the comments that n is the number of rows. So you need to allocate n rows each of length m. Therefore, the second for loop condition should be i < n. Also, you should check the return value of malloc for NULL in case it fails to allocate memory. I suggest the following change -

long long **a = malloc(n * sizeof(*a));
for(i = 0; i < n; i++)
    a[i] = malloc(m * sizeof(*a[i]));

Please note that a multi-dimensional array is not a fundamentally new type. It's simply an array of elements where each element itself is an array (for a 2D array), an array of arrays (for a 3D) array and so on. If you are using C99, you can allocate your array cleanly and succinctly as

int nrow = 4;  // number of rows
int ncol = 8;  // number of columns

// define arr to be a pointer to an array of ncol ints, i.e.,
// arr is a pointer to an object of type (int[ncol])
int (*arr)[ncol] = malloc(sizeof(int[nrow][ncol]));

// check the result of malloc for NULL
if(arr == NULL) {
    printf("malloc failed to allocate memory\n");
    // handle it
}

// do stuff with arr
for(int i = 0; i < nrow; i++)
    for(int j = 0; j < ncol; j++)
        arr[i][j] = i + j;

// after you are done with arr
free(arr);

You should also go through this - How do I work with dynamic multi-dimensional arrays in C?

Community
  • 1
  • 1
ajay
  • 9,402
  • 8
  • 44
  • 71
  • Hi, I can't allocate 2d arrays using the last example you gave, I'm using VS2019, shouln't support C99. – Sami Ben Dec 08 '19 at 00:23
1

You have three errors: The first is that you allocate only 5 secondary arrays, but in the input you loop over 6 of them.

The second problem is that array indices are zero-based, i.e. the index start at zero and goes to the size minus one.

The third problem is that you scan for two numbers (why?), but you provide only one destination pointer to scanf.

Some programmer dude
  • 400,186
  • 35
  • 402
  • 621
0

you just need

long *a = malloc(100*100*sizeof(long));

if you want one single big block of memory.

if you want an array of long* pointers and then each array to be in a separate block of memory go like this:

long **a = malloc(100*sizeof(long*));
for (i=0; i<100; i++) {
    a[i] = malloc(100*sizeof(long));
}

This creates 1 array of long* pointers, and then 1 array of 100 longs of each pointer, but I'm not sure now if you say a[10][15] for example if it would calculate position of the element as if its a continuous block. Check that out. :)

Nenad
  • 335
  • 1
  • 7
0

If you have C99 use Variable Length Array

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

int main(void) {
  unsigned rows, cols;
  printf("Enter rows and columns: ");
  fflush(stdout);
  scanf("%u%u", &rows, &cols);
  int (*a)[cols];                              // pointer to VLA
  a  = malloc(rows * cols * sizeof a[0][0]);
  if (a) {
    for (unsigned r = 0; r < rows; r++) {
      for (unsigned c = 0; c < cols; c++) {
        a[r][c] = r*c;
      }
    }
    printf("the element at [4, 2] is %d\n", a[4][2]);
    free(a);
  }
  return 0;
}

Otherwise, you need to calculate the indexing manually.

pmg
  • 106,608
  • 13
  • 126
  • 198
0

There are many problems in your code

First, you need long long a[100][100] but you only allocate enough space for ints

a[i] = malloc(m * sizeof(int));

You're also accessing arrays out-of-bound. Indexes start from 0 to array_length-1.

Another problem is that you scanf 2 int values but only provide the address for 1.

scanf("%d %d",&a[i][j]);

You can allocate a 100-element array of pointers, each points to an array of another 100-element array but that's not good because it takes time to do 100 mallocs, and the resulting memory most probably isn't contiguous, which makes it cache unfriendly. There are also a small memory overhead too because the memory allocator must round it up to the nearest block size and this is most probably powers of 2, which may be large as you allocate more and more elements in the first dimension.

You should declare a 1D array of size 100*100 instead. This will be much faster and improve cache coherency. To get the element at a[i][j] just do a[i*WIDTH + j]

long long* a = malloc(WIDTH*HEIGHT*sizeof(long long));
for (i = 0; i < WIDTH*HEIGHT; i++)
{
    scanf("%lld ",&a[i]);
}

for (i = 0; i < HEIGHT; i++)
{
    for (j = 0; j < WIDTH; j++)
    {
        printf("%lld ", a[i*WIDTH + j]);
    }
    printf("\n");
}
phuclv
  • 37,963
  • 15
  • 156
  • 475
  • Much better than doing the arithmetic oneself as `a[i*WIDTH + j]` is to use C99's Variable Length Arrays, as in the second half of this answer: http://stackoverflow.com/a/7326654/139746 – Pascal Cuoq May 08 '14 at 10:48
  • @PascalCuoq Yes I know. But if he doesn't use a C99 compiler or isn't allowed to use C99 features then the only way he can do is manually manage the array – phuclv May 08 '14 at 12:53