3

I created a program that prints 2 dimension matrix from external txt file. My program works if I define static matrix such as A[10][10]. But I want to allocate memory dynamically.

When I try this code:

int **A = (int **)malloc(N * N * sizeof(int));

There is error as following:

Unhandled exception at 0x00AC159B in dataStructures4.exe: 0xC0000005: Access violation writing location 0xCDCDCDCD.

On this loop:

for(i=0; i<N; i++){
    for(j=0; j<N; j++){
        A[i][j] = -1;
    }
}

I think I can't generate dynamic matrix correctly. How should I modify my code?

Mr. White
  • 204
  • 2
  • 12
  • A pointer to a pointer is not the same as an array of ints. – Kerrek SB Mar 08 '14 at 13:00
  • 1
    I think this question is similiar with [http://stackoverflow.com/questions/22186294/i-am-having-trouble-passing-a-multidimensional-variable-array-to-a-function-in-c](http://stackoverflow.com/questions/22186294/i-am-having-trouble-passing-a-multidimensional-variable-array-to-a-function-in-c), you can see it. Array is more likely the struct. So if you want to access them, you should see the second dimension to a structure: `int *A[10]` – QJGui Mar 08 '14 at 13:29

6 Answers6

8

You dynamically create 2d arrays as a pointer to chunk of int* pointers which point to a chunk of ints.

So there are two steps:

1) A to point to the first of a chunk of int*

int **A = (int **)malloc(N * sizeof(int*));

2) each of them to point to the first of a chunk of ints

for(i=0; i<N; i++){
    A[i] = (int *)malloc(N * sizeof(int));
}
Arjun Sreedharan
  • 11,003
  • 2
  • 26
  • 34
5

Use a pointer to an array of specific size:

You can use #define to define N, or use a variable:

int n = 10 ;
int (*A)[n] = malloc(n * n * sizeof(int));

This way you get a contiguous block of memory.

this
  • 5,229
  • 1
  • 22
  • 51
  • Too bad that `N` in `int (*A)[N]` must be known at compile time. This is not what he wants. – Filipe Gonçalves Mar 08 '14 at 13:03
  • 2
    @FilipeGonçalves No, you are wrong. You can do than no problem ( at least from c99 forward ). My proof( don't have time to search specs ) http://ideone.com/bW4Qeo – this Mar 08 '14 at 13:06
  • 1
    Sorry, my bad. Nice answer. I know C99 allows VLAs, I just wasn't thinking. +1 – Filipe Gonçalves Mar 08 '14 at 13:11
  • 1
    Ok then, but why wouldn't he use a 2D VLA in the first place? – Filipe Gonçalves Mar 08 '14 at 13:18
  • @FilipeGonçalves My answer does not have VLAs; maybe compiler doesn't support them or the array is too large for stack. – this Mar 08 '14 at 13:21
  • There is error as following; "IntelliSense: expression must have a constant value". So, if I use constant value how it could be dynamic memory allocated array? – Mr. White Mar 08 '14 at 13:21
  • @Mr.White because you allocated it dynamically. What compiler do you have? I'm guessing its VisualStudio, which doesn't support c99. – this Mar 08 '14 at 13:24
  • 2
    @self. Your answer surely makes use of VLAs. `A` is a pointer to a variable length array. If the compiler doesn't support VLAs, which seems to be the case, this won't work. – Filipe Gonçalves Mar 08 '14 at 13:25
  • @FilipeGonçalves Ok, my bad, you need c99 or better. – this Mar 08 '14 at 13:26
  • @self. We both got confused for a while :p But it's a good answer nonetheless. – Filipe Gonçalves Mar 08 '14 at 13:27
  • @self. Yes, my compiler is Visual Studio 2012. – Mr. White Mar 08 '14 at 13:28
  • @FilipeGonçalves Technically your still wrong because I don't use VLAs; but only a pointer to a VLA. :-) You still need c99 though. – this Mar 08 '14 at 13:28
  • @Mr.White That is primarily a c++ compiler. You will have to define your values with a #define, or get a better c compiler. – this Mar 08 '14 at 13:29
1

Remember that A[i][j] is the same as *(*(A+i)+j). Your code is broken because *(A+i) dereferences an invalid, uninitialized pointer. This happens on this line:

A[i][j] = -1;

The alternative is to use a dynamically allocated array of pointers, where each element points to another dynamically allocated array. You can do it like this:

int **array = malloc(N*sizeof(*array));
for (int i = 0; i < N; i++)
    array[i] = malloc(N*sizeof(*array[i]));

/* Use array[i][j]... */

Note that the memory layout is very different from that of a 2D array, but the expression array[i][j] will do what you want - it will "look" like you have a 2D array.

Filipe Gonçalves
  • 20,783
  • 6
  • 53
  • 70
1

Allocate each row separately, like here:

int **A = (int **)malloc(N * sizeof(int*));

for(i=0; i<N; i++){
    A[i] = (int *)malloc(N * sizeof(int));
}
Krzysztof Jabłoński
  • 1,890
  • 1
  • 20
  • 29
1

Same as an array, a 2 dimension matrix holds a contiguous address space. So theoretically there is a way to achieve this.

int m = 2;
int n = 4;
int *a = malloc(m*n*sizeof(int));
int **b = malloc(m*sizeof(int*));
for(int i=0, i<m, i++)
{
    b[i] = a+i*n;
}

In this manner, b can be used as a matrix as you demand. However, it will waste malloc(m*sizeof(int*)) to hold b.

or you can:

int m = 2;
int n = 4;
int *a = malloc(m*n*sizeof(int));

use a[m*i+j] as a[i][j]

bpceee
  • 416
  • 4
  • 17
0

Hope the below stuff is good. I haven't tested it, just providing you with syntax.

int** abc; // Your 2D array pointer abc[N][M]

abc = (int**)malloc(dim1_max * sizeof(int*)); // dim1_max is N
for (int i = 0; i < dim1_max; i++) {
  abc[i] = (int*)malloc(dim2_max * sizeof(int)); // dim2_max is M
}

[....your array used....]
//Once you allocate dynamically you need to free the memory. IMP point.
for (int i = 0; i < dim1_max; i++) {
  free(abc[i]);
}
free(abc);
Vishal R
  • 1,026
  • 1
  • 7
  • 21