问题
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
回答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.
来源:https://stackoverflow.com/questions/18456944/casting-from-void-to-int