-1

I have a dynamic 2D array stored in a void** pointer, and I am just wondering how I am supposed to cast/dereference the values so that they can be printed?

Here is an example of what I am trying to do:

/* Assume that I have a data structure called graph with some 
 * element "void** graph" in it and some element "int order" */

void foo(graph_t *graph)
{
    int **matrix;

    /*safe malloc works fine, it uses calloc to initialise it all to zeroes*/
    matrix = safe_malloc(graph->order * sizeof(int*)); 

    for (i = 0; i < graph->order; i++)
        matrix[i] = safe_malloc(graph->order * sizeof(int));

    /* storing matrix in the data structure */
    matrix = (int**)graph->graph;

    printf("%d\n", (int)graph->graph[2][2]);
}

When I try and compile it, the compiler gives me the warning: "dereferencing 'void *' pointer", and the error: "invalid use of void expression".

What should I do to cast the void** pointer so that I can print elements from graph->graph?

EDIT:

thanks for everyone's help; i cant make graph->graph of type int** because it needs to hold mulitple types of data, the only one i am having trouble with implementing is the int** array.

i changed matrix = (int*)graph->graph to graph->graph = (void*)matrix and that worked fine, i am able to print elements of the array, however now if i implement a separate function:

void print_foo(graph_t *graph)
{
    int i,j;

    for (i = 0; i < graph->order; i++)
    {
        for(j = 0; j < graph->order; j++)
        {
            printf("%d ", ((int**)graph->graph)[i][j]);
        }
        putchar('\n');
    }
}

it just gives me a segmentation fault, however if i run that block of code in the original foo(graph_t *graph), it prints the 2D array fine.

can someone please explain what is happening to graph->graph so that it wont print if i call it from a different function

alk
  • 69,737
  • 10
  • 105
  • 255
guskenny83
  • 1,321
  • 14
  • 27
  • Note: You're leaking memory with this line: `matrix = (int**)graph->graph;`. You just assigned `matrix` the return of a `malloc()` call. Second, what is `graph_t`? It looks like it has a member (`graph`) that is a `void**` You can't dereference a `void*` (which is what your second index is doing). There is no "type" there, and thus no mechanism of knowing anything about it. There is no reason to have a void** for your "hidden" array. A `void*` will work, but you need to understand pointers more before that gels. – WhozCraig Aug 27 '13 at 04:39
  • See also [Casting `void **` to 2D array of `int` in C](http://stackoverflow.com/questions/18440205/casting-void-to-2d-array-of-int-c). – Jonathan Leffler Aug 27 '13 at 05:28

1 Answers1

1

Given:

typedef struct graph_t
{
    int order;
    void **graph;
} graph_t;

and assuming that you allocate graph->graph as an array of int * and a series of arrays of int, then you can, if you must, write:

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

typedef struct graph_t
{
    int order;
    void **graph;
} graph_t;

extern void *safe_malloc(size_t n);
extern void foo(graph_t *graph);

void foo(graph_t *graph)
{
    int **matrix;

    /*safe malloc works fine, it uses calloc to initialise it all to zeroes*/
    matrix = safe_malloc(graph->order * sizeof(int*)); 

    for (int i = 0; i < graph->order; i++)
        matrix[i] = safe_malloc(graph->order * sizeof(int));

    /* storing matrix in the data structure */
    graph->graph = (void **)matrix; // Reverse order of assignment
    // C compiler complains without the cast - the cast is nasty!

    printf("%d\n", ((int **)graph->graph)[2][2]);
}

The code should check that graph->order >= 3 to avoid overflow problems.

However, the structure is pretty nasty, and the necessary casting in the printf() statement is enough to make you realize why it is nasty. You'd be far better off with an int **graph; in the structure:

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

typedef struct graph_t
{
    int order;
    int **graph;
} graph_t;

extern void *safe_malloc(size_t n);
extern void foo(graph_t *graph);

void foo(graph_t *graph)
{
    int **matrix;

    matrix = safe_malloc(graph->order * sizeof(int*)); 

    for (int i = 0; i < graph->order; i++)
        matrix[i] = safe_malloc(graph->order * sizeof(int));

    graph->graph = matrix;

    printf("%d\n", graph->graph[2][2]);
}

Both of these compile without warnings, even under stringent warning levels. Neither has formally been tested by creating a main() function to exercise it. You also need to have a function bar(graph_t *graph) to release the allocated memory, of course.

Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278
  • thanks a lot for your help. i have to keep graph as a void** pointer so that i am able to store multiple types of data in that space. i have a follow-up question based your response, but i might just edit my original question so i can use code.. – guskenny83 Aug 27 '13 at 05:21