Integer Double pointer in a struct

I am writing a C program to transpose a matrix and to test it I have a structure which contains a pointer to a set of pointers , to which I am allocating memory using malloc in a separate function. Now, my question is: can i initialize the matrix in the following format?:

cases[0].matq={{1,2,3,4},{5,6,7,8},{9,10,11,12},{13,14,15,16}};
cases[0].matq={1,5,9,13,2,6,10,14,3,7,11,15,4,8,12,16}; //or like this

where cases is an array of type struct.

Upvotes: 0

Views: 187

Answers (2)

Floris
Floris

Reputation: 46445

Instead of having a pointer to a set of pointers for which you explicitly allocate memory, why not do the following: store the 2D array in the conventional way, then have the pointers in your structure point to it. I have made a mini complete (compiles, runs) program to show how this can work (note - this was edited after comments from @ryyker):

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

int main(void) {

  int A[4][4]={{1,2,3,4},{5,6,7,8},{9,10,11,12},{13,14,15,16}}; // conventional initialization
  int **pp; // this is really an element of your structure
  pp = malloc(4 * sizeof (int *)); // four pointers to int

  int ii, jj;
  for(ii=0; ii<4; ii++) pp[ii] = &A[ii][0]; // point to the original matrix

  // show that it works:
  for(ii=0; ii<4; ii++) {
    for(jj=0; jj<4; jj++) {
      printf("%d ", pp[ii][jj]);
    }
    printf("\n");
  }
}

This gives the output you would expect:

1 2 3 4 
5 6 7 8 
9 10 11 12 
13 14 15 16 

As you can see, with this code the array is initialized in the "normal" way, and you can address elements in this array by double dereferencing. No copies are made - all you need is the array of pointers.

It is not completely clear to me why you are doing what you are doing; so it may be that this approach doesn't work for you - but in that case I am sure you will let me know in the comments and we can tweak it.

further update

Based on various comments, perhaps this is a good way to think about your problem:

// all the test cases in a 3D array:
int testCases[5][4][4]={ \
    {{1,2,3,4},{2,3,4,5},{3,4,5,6},{4,5,6,7}}, \
    {{2,3,4,5},{3,4,5,6},{4,5,6,7},{1,2,3,4}}, \
    {{3,4,5,6},{4,5,6,7},{1,2,3,4},{2,3,4,5}}, \
    {{4,5,6,7},{1,2,3,4},{2,3,4,5},{3,4,5,6}}};

int **pp; // this is really an element of your structure
pp = malloc(4 * sizeof (int *)); // four pointers to int
                                 // only allocate once
int ii, jj; // usual counters
int **qq; // place for the result

// create space: now we need two calls to malloc to get both the pointers, and the space
qq = malloc(4 * sizeof(int*));
qq[0]=malloc(4*4*sizeof(int)); // total block is 16 int long
for(ii=1;ii<4;ii++) qq[ii] = qq[0] + ii * 4 * sizeof(int); // set up other pointers

int tc;
for(tc = 0; tc < 5; tc++) { // loop over the test cases
  // make pp point to a test case
  for(ii=0; ii<4; ii++) pp[ii] = &testCases[tc][ii][0];
  doTranspose(pp, qq); // assuming that the result of transposing pp is in qq
  printMatrix(qq);     // some code that prints the result
}

And your doTranspose might look like:

void doTranspose(int **pp, int **qq) {
  int ii, jj;
  for(ii=0; ii<4; ii++) {
    for(jj=0; jj<4; jj++) {
      qq[ii][jj] = pp[jj][ii];
    }
  }
}

Copying the result into a different matrix makes the code a little easier. If you want to do an in-place transpose, you could do

void inplaceTranspose(int **pp) {
  int ii, jj, temp;
  for(ii=0; ii<4; ii++) {
    for(jj=0; jj<4; jj++) {
      temp = pp[ii][jj];
      pp[ii][jj]=pp[jj][ii];
      pp[jj][ii]=temp;
    }
  }
}

void printMatrix(int **pp){
  int ii, jj;
  for(ii=0; ii<4; ii++) {
    for(jj=0; jj<4; jj++) {
      printf("%4d ", pp[ii][jj]);
    }
    printf("\n");
  }
}

Upvotes: 1

ryyker
ryyker

Reputation: 23236

Regarding can i initialize the matrix in the following format?:

cases[0].matq={{1,2,3,4},{5,6,7,8},{9,10,11,12},{13,14,15,16}};  
//(even if cases[0].matq happened to be `int **`, which is not defined in your question)

No. It is not legal to do that:

OR this:

 int **b={{1,2,3,4},{5,6,7,8},{9,10,11,12},{13,14,15,16}};  

However, it is legal to do this:

int b[4][4]={{1,2,3,4},{5,6,7,8},{9,10,11,12},{13,14,15,16}};

Regarding to which I am allocating memory using malloc in a separate function:
Since you are creating memory for the 2 dimensional array using calloc(), your array elements would already be initialized to 0. To make further assignments use a loop, or sequential statements to assign values to each member individually.

Given you have initialized the array using malloc() successfully, you could assign pseudo random numbers to the array in a fashion such as this:

example:

//...
srand(clock());
for(i=0;i<r;i++)
    for(j=0;j<c;j++)
        b[r][c]=rand();  
//...

Upvotes: 0

Related Questions