Returning an array of pointers.

Hopeing someone can help with how to return an array of pointers to structures. But the real trick is that the function return type must be char *.
So he is what I got:

int main()
{
// usable array of pointers.
SomeSeq **array_ptrs = NULL;

char * b, q, *r;


b=getbuf(array_ptrs);

q = *b;




}
char * getbuf(SomeSeq **ptrs)
{
int rows ;
int cols ;

char buff[8] ;

int n = GetNumberOfSomeSeqsToGenerate();

/* allocate the memory for the array */


ptrs = malloc(rows * sizeof(SomeSeq *));
if( ptrs == NULL)
{
fprintf(stderr, "out of memory\n");
return (char *) buff;
}
for(int i = 0; i < rows; i++)
{
ptrs[i] = malloc(cols * sizeof(SomeSeq));
if( ptrs[i] == NULL)
{
fprintf(stderr, "out of memory\n");
return (char *) buff;
}
}



return (char *) buff;
}

Am I on the right track, that is an array of pointers to the SomeSeq struct right?
Am I passing it in correctly?
Last edited on
Your getbuf() needs one more level of indirection:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
#include <stdio.h>
#include <stdlib.h>

/* Here, I return the result via an argument pointer.
 * This is the same as if I wanted to return an int value:
 * I would create a function like:
 *   foo( int* n )
 * Except instead of 'int' the type is 'double**'.
 * Hence the (double**)*, or 'double***'.
 */
void create_square_matrix( double*** result, unsigned size )
  {
  unsigned m;
  *result = (double**)malloc( sizeof( double* ) * size );
  for (m = 0; m < size; m++)
    {
    (*result)[ m ] = (double*)malloc( sizeof( double ) * size );
    }
  }

/* This function doesn't change the memory location of the
 * matrix, so no extra indirection is needed.
 */
void identity_square_matrix( double** matrix, unsigned size )
  {
  unsigned m, n;
  for (m = 0; m < size; m++)
  for (n = 0; n < size; n++)
    {
    matrix[ m ][ n ] = (m == n) ? 1.0 : 0.0;
    }
  }

/* Likewise.
 */
void print_square_matrix( double** matrix, unsigned size )
  {
  unsigned m, n;
  for (m = 0; m < size; m++)
    {
    for (n = 0; n < size; n++)
      printf( "%1.0f ", matrix[ m ][ n ] );
    printf( "\n" );
    }
  }

/* This function works a bit differently.
 * Instead of taking an argument pointer, it returns the
 * new value.
 */
double** free_square_matrix( double** matrix, unsigned size )
  {
  unsigned m;
  for (m = 0; m < size; m++)
    free( matrix[ m ] );
  free( matrix );
  return NULL;
  }

int main()
  {
  double** M;

  create_square_matrix(   &M, 10 );  /* Remember to pass the address of the matrix pointer */
  identity_square_matrix(  M, 10 );
  print_square_matrix(     M, 10 );
  M = free_square_matrix(  M, 10 );  /* Notice how we get a new value for M via the function result */

  return 0;
  }


Personally, however, I would abstract all this into a struct and use it in an object-oriented way:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
#include <stdio.h>
#include <stdlib.h>

typedef struct
  {
  double** data;
  unsigned size;
  }
  square_matrix_t;

square_matrix_t create_square_matrix( unsigned size )
  {
  square_matrix_t result;
  unsigned        m;
  result.data = (double**)malloc( sizeof( double* ) * size );
  for (m = 0; m < size; m++)
    {
    result.data[ m ] = (double*)malloc( sizeof( double ) * size );
    }
  result.size = size;
  return result;
  }

void identity_square_matrix( square_matrix_t matrix )
  {
  unsigned m, n;
  for (m = 0; m < matrix.size; m++)
  for (n = 0; n < matrix.size; n++)
    {
    matrix.data[ m ][ n ] = (m == n) ? 1.0 : 0.0;
    }
  }

void print_square_matrix( square_matrix_t matrix )
  {
  unsigned m, n;
  for (m = 0; m < matrix.size; m++)
    {
    for (n = 0; n < matrix.size; n++)
      printf( "%1.0f ", matrix.data[ m ][ n ] );
    printf( "\n" );
    }
  }

square_matrix_t free_square_matrix( square_matrix_t matrix )
  {
  unsigned m;
  square_matrix_t result = { 0 };
  for (m = 0; m < matrix.size; m++)
    free( matrix.data[ m ] );
  free( matrix.data );
  return result;
  }

int main()
  {
  square_matrix_t M;

  M = create_square_matrix( 10 );
  identity_square_matrix( M );
  print_square_matrix(    M );
  M = free_square_matrix( M );

  return 0;
  }


Hope this helps.
Thanks for the reply. I tried your create_square_matrix function but the programa crashes on this line: *result = (double**)malloc( sizeof( double* ) * size );
Hey nevermind I wasnt following all of your directions, its good for the time being. Thanks again for the help.
Your code is brilliant. I'm still confused on the levels of indirection and syntax required to process them but I also have one last problem. I thought it would be easy but I can't figure it out. Lets say I used your create_square_matrix,(from the first straight C example) this returns an empty usable block of pointers to doubles right? How would I fill that block with data with a function that looks like this:
Double * Somefunc(void);
Whats getting me is its doesn't take anything in so would I just reallocate all that again inside this function and return the double?
It might help to use some typedefs to separate the types.
1
2
3
4
5
/* This is the type we are using */
typedef double** matrix_t;

/* Here is a pointer (a reference) to that type */
void create_matrix( matrix_t* result, unsigned size );

If you substitute the type in with that prototype, you'll get a (double**)*, which is the same as a double***.

To return the type properly, you only need to properly allocate memory and return the starting address:
1
2
3
4
5
6
7
8
9
typedef double** matrix_t;
matrix_t create_matrix( unsigned size )
  {
  unsigned n;
  matrix_t result;
  result = (matrix_t)malloc( sizeof( double* ) * size );
  for (n = 0; n < size; n++)
    result[ n ] = (double*)malloc( sizeof( double ) * size );
  }
1
2
3
4
5
6
7
8
9
int main()
  {
  matrix_t M = create_matrix( 10 );

  ...

  M = free_matrix( M, 10 );
  return 0;
  }

Thereafter, you only need the address of the data you wish to modify:
1
2
3
4
5
6
7
void identity_matrix( matrix_t M, unsigned size )
  {
  unsigned m, n;
  for (m = 0; m < size; m++)
  for (n = 0; n < size; n++)
    M[ m ][ n ] = (m == n) ? 1.0 : 0.0;
  }


BTW, both examples are straight C -- I have not used any C++. Only some data encapsulation by putting both the pointer and the size of the matrix together in a struct. That way you only need to pass around the struct -- instead of having to explicitly remember the size of each matrix every time you use it, as in this latest example.

Hope this helps.
How would I fill M with data after create_matrix?
//prototype
Double *GetData(void);

//somewhere in main
M[0][0] = GetData();



error C2679: binary '=' : no operator found which takes a right-hand operand of type
Topic archived. No new replies allowed.