views:

335

answers:

4

What i need is a function that modifies given pointer to 2d matrix like this:

void intMatrixAll(int row, int col, int **matrix);

Now, a function should allocate memory and the matrix could be used. Rows and cols are given at run-time.

#include <stdio.h>
#include <stdlib.h>
#define PRINTINT(X) printf("%d\n", X);
void intMatrixAll(int row, int col, int **matrix);

int main(void) {
   int testArrRow = 4;
   int testArrCol = 6;
   int **testMatrix = NULL;
   intMatrixAll(testArrRow, testArrCol, testMatrix);
   testMatrix[2][2] = 112; //sementation fault here :(
   PRINTINT(testMatrix[2][2]);
   system("PAUSE");
   return 0;
}

void intMatrixAll(int row, int col, int **matrix) {
   printf("intMatrixAll\n");
   //allocate pointers:
   matrix = malloc(row * sizeof(int *));
   if(matrix == NULL) printf("Failed to allocate memmory.\n");
   for(int i=0; i<row; i++) {
      //allocate space for cols: 
      matrix[i] = malloc(col * sizeof(int));
      if(matrix[i] == NULL) {
         printf("Failed to allocate memmory for arr[%d].\n", i);
         exit(0);
      }
   }
}

Why am i getting error?

+5  A: 

Test matrix is still NULL. You need to return the newly allocated pointer from intMatrixAll(). Either return the value from the function, or pass in the address of testMatrix so it can be set.

#include <stdio.h>
#include <stdlib.h>
#define PRINTINT(X) printf("%d\n", X);
void intMatrixAll(int row, int col, int **matrix);

int main(void) {
   int testArrRow = 4;
   int testArrCol = 6;
   int **testMatrix = NULL;
   intMatrixAll(testArrRow, testArrCol, &testMatrix);
   testMatrix[2][2] = 112; //sementation fault here :(
   PRINTINT(testMatrix[2][2]);
   system("PAUSE");
   return 0;
}

void intMatrixAll(int row, int col, int ***matrix) {
   printf("intMatrixAll\n");
   //allocate pointers:
   *matrix = malloc(row * sizeof(int *));
   if(*matrix == NULL) printf("Failed to allocate memmory.\n");
   for(int i=0; i<row; i++) {
      //allocate space for cols: 
      *matrix[i] = malloc(col * sizeof(int));
      if(*matrix[i] == NULL) {
         printf("Failed to allocate memmory for arr[%d].\n", i);
         exit(0);
      }
   }
}
FigBug
Returning an `int **` would be better style than taking an `int ***` parameter.
Dave Hinton
+1  A: 

Because modifying matrix inside intMatrixAll() does not modify testMatrix in main(). If you want to be able to modify main's variable, you need to pass a pointer to it. So you need to change intMatrixAll to:

void intMatrixAll(int row, int col, int ***matrix)

Inside intMatrixAll, you'll now need to change matrix to *matrix (and for when you are indexing it, you'll want (*matrix)[...].

Finally, you need to change your call to intMatrixAll to:

intMatrixAll(testArrRow, testArrCol, &testMatrix);

The reason why is that C only supports pass-by-value and pass-by-value does not support the called function changing the value of a variable in the caller.

In order to modify the value of a variable in the caller, you need to pass a pointer to the variable and then have the called function dereference it.

R Samuel Klatchko
This works! Thanks Samuel! So i need to dereference the matrix arg with * ... I forgot about pass-by-value and pass-by-reference rule. I thought that applies only to variables, not pointers.
Martin Berger
`testMatrix` *is* a variable.
Dave Hinton
Damn! What i meant to say is basic C data types like int and char. So i understood that when you pass a pointer to function that you actually passed-by-reference. Wrong. Thanks.
Martin Berger
@Martin - it is confusing at first because you use pointers to simulate pass-by-reference (i.e., if you want to pass an int by reference you use a pointer to int). But in all cases, the actual parameter is always pass-by-value.
R Samuel Klatchko
Hey Sam, can you help me some more? I thought i understood this (*matrix)[...] part but i didnt :(i used this to print value in function: PRINTINT((*m1)[1][3]);and i thought that it is the same as *(*(*(m1+1)+3))so what actually is (*m1)[1][3]? More precisely why (*m1), why not just *m1[1][3]??
Martin Berger
PS, how do i make code tags manually in these replies? I thought <code> </code> but wont work.
Martin Berger
Mar - The difference is that *m1[x] works out to *(m1[x]) so you are indexing then dereferencing rather then vice versa. Since m1 points to a single pointer (which itself points to an array), you want to dereference then index. Drawing pictures (where a single pointer is a box and an array is a rectangle) is very helpful in these situations.
R Samuel Klatchko
Uh.. Back to the books... or drawing. Thank for explaining :)
Martin Berger
A: 
tommieb75
Yes, this apprach works, as Samuel's. Thanks for detailed explanation. To ask you something, do you, or others here, knows about some book or web site where i could learn pointers in depth. All i was founding on web are begginer level pointer stuff, and i wold like to learn them. You know, the book which would explain this int *(*list[ MAX ])(); and similar woundrousities.
Martin Berger
@Martin Berger: I do not know if its still in print but try amazon.com - "Expert C Programming - Deep C Secrets" by Peter Van Der Linden. Excellent stuff - read it, lived it, breathed it and ate it!!! ;)
tommieb75
@tommieb75: Now thats the stuff! Pointers, memmory alloc and compiling. And in depth! Tnx for recomendation!
Martin Berger
@Martin Berger: Excellent! Please recommend others to stumble on pointers et al to go buy the book - it is 100% worth it and will make you proficient in C! ;)
tommieb75
A: 

Thank YOU this helped me as well

vect