Related
i am trying do dynamicly allocate a matrix which is inside a struct, also if anyone can also tell me how to send it to the function so i don't have to declare my struct variable globally i would really apreciate it, cuz i can't seem to figure it out
#include <stdio.h>
#include<stdlib.h>
#include <stdbool.h>
struct matrice_dinamica{
int linii, coloane;
int **matrice;
};
struct matrice_dinamica* v = NULL;
void comanda_L_citire_matrice(int i)
{
scanf("%d %d", &v[i].linii, &v[i].coloane);
int v[i].(*matrice)[v[i].coloane] = malloc (sizeof(int[v[i].linii][v[i].coloane]));
for(int x = 0; x < v[i].linii; x++){
for(int y = 0; y < v[i].coloane; y++){
scanf("%d", &v[i].matrice[x][y]);
}
}
}
int main(int argc, char const *argv[])
{
v = (struct matrice_dinamica*)malloc(sizeof(struct matrice_dinamica));
there are more things in the main function so i only gave what i thought usefull cuz the error i get is in the function
the error i get is error: expected expression before '.' token
To avoid double pointers, int **matrice cannot be used because that is a double pointer. The storage for the matrix can be "flattened" into a single dimension and the positions of the elements for each (row,column) coordinate can calculated arithmetically as row * num_columns + column. For example:
struct matrice_dinamica{
int linii, coloane;
int *matrice; // flattened
};
// Get pointer to start of a row
int *matrice_row(struct matrice_dinamica *m, int x)
{
return m->matrice + x * m->coloane;
}
// Get pointer to an element
int *matrice_elp(struct matrice_dinamica *m, int x, int y)
{
return matrice_row(m, x) + y;
}
// Get value of an element
int matrice_el(struct matrice_dinamica *m, int x, int y)
{
return *matrice_elp(m, x, y);
}
// Store value in an element
void matrice_el_store(struct matrice_dinamica *m, int x, int y, int val)
{
*matrice_elp(m, x, y) = val;
}
void comanda_L_citire_matrice(struct matrice_dinamica *m)
{
int *md;
scanf("%d %d", &m->linii, &m->coloane);
m->matrice = malloc(m->linii * m->coloane * sizeof(int));
md = m->matrice;
for(int x = 0; x < m->linii; x++){
for(int y = 0; y < m->coloane; y++){
scanf("%d", md++);
}
}
}
I came across this question while looking for an effective way to allocate large multi-dimensional arrays contiguously in memory. The accepted answer suggests that for a 3D array of size sz[0] x sz[1] x sz[2] one should use this method, which is currently melting my feeble brain:
int (*a)[sz[1]][sz[2]] = calloc(sz[0], sizeof(*a));
...
free(a)
the left hand of that statement looks like a 2D array of int * allocated on the stack. The right side is a single (?!) call to calloc() that allocates int * on the heap. Since sizeof(*a)==sizeof(int *) (right?) this looks like too few allocations to make any sense, since it appears to allocate sz[0]x int * bytes, and yet it works to index over the full intended size of the array.
Can someone please help me understand how exactly this definition works to produce the intended result? Is the C compiler repeating the call to calloc for every entry in the table defined on the left? And if so, how does a single call to free() suffice to get rid of it? Does the resulting array reside entirely on the heap, or is it mixing a reference table on the stack that points to memory allocated on the heap?
Here is some code with a similar principle that maybe is easier to understand at first:
typedef int THING[5][6]; // THING means a contiguous array of 5x6 ints
THING arr[4]; // arr is a contiguous array of 4 THINGs
THING *first = &arr[0]; // The expression *first would yield the first thing.
Hopefully you recognize the last two lines here as being common syntax for non-dynamic allocation of any array, and referring to the array's first element. That works just the same whether or not THING is itself an array.
Now, &arr[0] points to a memory location that is the start of a contiguous block of ints of size 4x5x6. if you use dynamic allocation to make that block it looks like:
THING *first = malloc( sizeof(int[4][5][6]) );
If we expand out the typedef in this last line it looks like:
int (*first)[5][6] = malloc( sizeof(int[4][5][6]) );
The code in your question is the same as this last line , except that:
it uses variables instead of hardcoded integers (which is allowed since C99).
it uses calloc instead of malloc.
it uses a more robust syntax for calculating the size to allocate, see here for explanation.
To not rely on VLAs, but still use one continuous region of memory you could use this approach:
int *** int_array_3d_allocate(size_t x, size_t y, size_t z)
{
int *** result;
size_t n = x;
size_t s = n * sizeof *result; /* x vector of pointer to int** */
n *= y;
s += n * sizeof **result; /* x*y vectors of pointer to int* */
n *= z;
s += n * sizeof ***result; /* x*y*z int */
/* allocate it */
result = malloc(s);
if (result)
{
/* make the int** vector point to the int* vectors: */
for (size_t i = 0; i < x; ++i)
{
result[i] = (int**) ((char*) result) +
(x * sizeof *result +
i * y * sizeof **result);
}
/* make the int* vectors point to the int vectors: */
for (size_t i = 0; i < x*y; ++i)
{
((int**) ((char*) result + x * sizeof *result))[i] = (int*) ((char*) result) +
(x * sizeof *result + x*y * sizeof **result
+ i * sizeof ***result);
}
}
return result;
}
Version of the above code taking care of correct alignment of the int* and the int** blocks:
#include <stdalign.h>
int *** int_array_3d_allocate(size_t x, size_t y, size_t z)
{
int *** result;
size_t n = x;
size_t s = n * sizeof *result; /* x vector of pointer to int** */
size_t y_off = s % alignof **result
?alignof **result - s % alignof **result :0;
n *= y;
s += n * sizeof **result; /* x*y vectors of pointer to int* */
size_t z_off = s % alignof ***result
?alignof ***result - s % alignof ***result :0;
n *= z;
s += n * sizeof ***result; /* x*y*z int */
/* allocate it */
result = malloc(s);
if (result)
{
/* make the int** vector point to the int* vectors: */
for (size_t i = 0; i < x; ++i)
{
result[i] = (int**) ((char*) result) + y_off +
(x * sizeof *result +
i * y * sizeof **result);
}
/* make the int* vectors point to the int vectors: */
for (size_t i = 0; i < x*y; ++i)
{
((int**) ((char*) result + x * sizeof *result + y_off))[i] = (int*) ((char*) result) + y_off +
(x * sizeof *result + x*y * sizeof **result + z_off +
+ i * sizeof ***result);
}
}
return result;
}
Use it like this:
#include <stdlib.h>
#include <stdio.h>
int *** int_array_3d_allocate(size_t x, size_t y, size_t z);
int main(void)
{
const size_t x = 2;
const size_t y = 3;
const size_t z = 5;
int *** int_array_3d = int_array_3d_allocate(x, y, z);
if (!int_array_3d)
{
perror("int_array_3d_allocate() failed");
}
else
{
for (size_t i = 0; i < x; ++i)
{
for (size_t j = 0; j < y; ++j)
{
for (size_t k = 0; k < z; ++k)
{
int_array_3d[i][j][k] = (int)(i*j*k);
}
}
}
/* do stuff with the continuous array of ints.
Just be aware that the 1st int only is located at address:
(char* int_array_3d) +
(x * sizeof *int_array_3d + x*y * sizeof **int_array_3d)
*/
free(int_array_3d);
}
}
If the array is handed off to functions, it decays into a pointer-to-pointer-to-pointer-to-int, making it unwieldy; one has to pass all the extra size information, too, or pass a pointer to a fixed size; see What is array decaying? A different way of handling arrays with multiple dimensions is an object which has the dimensions encoded within the object. This will compile in C90,
#include <stdlib.h> /* mallc, free, EXIT_ */
#include <errno.h> /* errno */
#include <stdio.h> /* perror, printf, fput[c|s] */
struct IntCube { size_t x, y, z; /* C99 supports FAM; would be useful. */ };
/** Returns a `struct IntCube` with `x`, `y`, `z` dimensions or null and
`errno` may be set. The caller is responsible for calling `free`. */
static struct IntCube *IntCube(const size_t x, const size_t y, const size_t z) {
struct IntCube *cube;
size_t xy_size, xyz_size, data_size, cube_size;
if(!x || !y || !z) return 0;
/* Check for overflow; <https://stackoverflow.com/q/1815367/2472827>. */
xy_size = x * y;
xyz_size = xy_size * z;
data_size = xyz_size * sizeof(int);
cube_size = sizeof cube + data_size;
if(xy_size / x != y
|| xyz_size / xy_size != z
|| data_size / xyz_size != sizeof(int)
|| cube_size < data_size) { errno = ERANGE; return 0; }
/* Allocate memory. */
if(!(cube = malloc(cube_size))) return 0; /* POSIX has defined errors. */
cube->x = x;
cube->y = y;
cube->z = z;
return cube;
}
static int *int_cube_get(const struct IntCube *cube,
const size_t x, const size_t y, const size_t z) {
return (int *)(cube + 1) + z * cube->y * cube->x + y * cube->x + x;
}
typedef void (*IntCubeAction)(const size_t x, const size_t y, const size_t z,
int *pnumber);
typedef void (*BinaryAction)(int bin);
/** Goes through `cube` and performs `action` on each number. It will call
optional binary action `bin` each time there is an
start(false)/end(true)-of-x/y. */
static void IntCubeForEach(struct IntCube *const cube,
const IntCubeAction action, const BinaryAction bin) {
size_t x, y, z;
if(!cube || !action) return;
for(z = 0; z < cube->z; z++) {
if(bin) bin(0);
for(y = 0; y < cube->y; y++) {
if(bin) bin(0);
for(x = 0; x < cube->x; x++) {
action(x, y, z, int_cube_get(cube, x, y, z));
}
if(bin) bin(1);
}
if(bin) bin(1);
}
}
/** #implements IntCubeAction */
static void fill_with_xyz(const size_t x, const size_t y, const size_t z,
int *pnumber) {
*pnumber = (x + 1) * (y + 1) * (z + 1);
}
/** #implements IntCubeAction */
static void print_cube(const size_t x, const size_t y, const size_t z,
int *pnumber) {
(void)y, (void)z;
printf("%s%d", x ? ", " : "", *pnumber);
}
/** #implements BinaryAction */
static void print_cube_corners(int bin) {
printf("%s", bin ? " }" : "{ ");
}
int main(void) {
struct IntCube *cube = 0;
int status = EXIT_FAILURE;
if(!(cube = IntCube(4, 3, 3))) goto catch;
IntCubeForEach(cube, &fill_with_xyz, 0);
IntCubeForEach(cube, &print_cube, &print_cube_corners);
fputc('\n', stdout);
status = EXIT_SUCCESS;
goto finally;
catch:
perror("Cube");
finally:
free(cube);
return status;
}
{ { 1, 2, 3, 4 }{ 2, 4, 6, 8 }{ 3, 6, 9, 12 } }{ { 2, 4, 6, 8 }{ 4, 8, 12, 16 }{ 6, 12, 18, 24 } }{ { 3, 6, 9, 12 }{ 6, 12, 18, 24 }{ 9, 18, 27, 36 } }
This creates a dependence on struct IntCube, but with the dependence, one can calculate the size at runtime.
I don't know how to set a localization of each neuron in map. This is a neuron and map:
typedef struct _neuron
{
mfcc_frame *frames;
char *name;
double *weights;
int num_weights;
int x;
int y;
} neuron;
typedef struct _map
{
neuron *lattice;
int latice_size;
double mapRadius;
int sideX, sideY;
int scale;
} map;
If i have more of one word equal, how calculate a distance between the pattern input (word) and my neuron.
I not sure about the weights. I define the weights as the amount of mfcc features of a word, but in training I need to update this weight according to the distance between the neurons. I'm using the Euclidean distance between the neurons. But the doubt is how to update the weights. Here the code of init map and neurons
void init_neuron(neuron *n, int x, int y, mfcc_frame *mfcc_frames, unsigned int n_frames, char *name){
double r;
register int i, j;
n->frames = mfcc_frames;
n->num_weights = n_frames;
n->x = x;
n->y = y;
n->name = malloc (strlen(name) * sizeof(char));
strcpy(n->name, name);
n->weights= malloc (n_frames * sizeof (double));
for(i = 0; i < n_frames; i++)
for(j = 0; j < N_MFCC; j++)
n->weights[i] = mfcc_frames[i].features[j];
printf("%s lattice %d, %d\n", n->name, n->x, n->y);
}
init map:
map* init_map(int sideX, int sideY, int scale){
register int i, x, y;
char *name = NULL;
void **word_adresses;
unsigned int n = 0, count = 0;
int aux = 0;
word *words = malloc(sizeof(word));
map *_map = malloc(sizeof(map));
_map->latice_size = sideX * sideY;
_map->sideX = sideX;
_map->sideY = sideY;
_map->scale = scale;
_map->lattice = malloc(_map->latice_size * sizeof(neuron));
mt_seed ();
if ((n = get_list(words))){
word_adresses = malloc(n * sizeof(void *));
while (words != NULL){
x = mt_rand() %sideX;
y = mt_rand() %sideY;
printf("y : %d x: %d\n", y, x);
init_neuron(_map->lattice + y * sideX + x, x, y, words->frames, words->n, words->name);
word_adresses[count++] = words;
words = words->next;
}
for (i = 0; i < count; i++)
free(word_adresses[i]);
free(word_adresses);
aux++;
}
return _map;
}
In the Kohonen SOM, the weights are in the feature space, so that means that each neuron contains one prototype vector. If the input is 12 MFCCs, then each input might look like a vector of 12 double values, so that means each neuron has 12 values, one for each of the MFCCs. Given an input, you find the best matching unit, then move the 12 codebook values for that neuron towards the input vector a small amount that is based on the learning rate.
I'm currently working on this : I generate a Paraview .vtm file that contains several .vtr files. Each .vtr file contains values, and coordinates, like this, assuming I'm working on a dimension of 8 :
<PointData Scalars="U">
<DataArray type="Float32" Name="U" format="ascii">
<!-- 8*8*8 values -->
</DataArray>
</PointData>
<Coordinates>
<DataArray type="Float32" Name="x" format="ascii">
<!-- 8 x values -->
</DataArray>
<DataArray type="Float32" Name="y" format="ascii">
<!-- 8 y values -->
</DataArray>
<DataArray type="Float32" Name="z" format="ascii">
<!-- 8 z values -->
</DataArray>
</Coordinates>
I use a quadridimensionnal array to store my values : float ****tab, with tab[s][x][y][z], where :
s is the current split step. It increments everytime I start working on the next .vtr file.
x, y, z the values.
Now is what causes me trouble : the coordinates where I have to place these points can be anything. It can be constant (following a step, like 0, 0.1, 0.2, and so on), or not.
I store the coordinates in three arrays : x[], y[], z[]. My goal is to cut the set of values into smaller cubes. Let's assume I split my values into 8 files (2^3 files), I have to retrieve the correct coordinates for 8 small cubes. And I can't find a way to do that.
I'm pretty sure my data structures choice is terrible, could someone give me some help with that ?
EDIT :
Here is the function generating my four-star array :
float**** fill_array_random4d(int split, int size)
{
float**** ret;
ret = malloc(sizeof(float***) * split);
for (int i = 0; i < split; i++)
{
ret[i] = malloc(sizeof (float**) * size);
for (int j = 0; j < size; j++)
{
ret[i][j] = malloc(sizeof (float*) * size);
for (int k = 0; k < size; k++)
{
ret[i][j][k] = malloc(sizeof (float) * size);
for (int l = 0; l < size; l++)
ret[i][j][k][l] = rand() % 100;
}
}
}
return ret;
}
It's a pretty basic stuff. Right now I'm using random values.
Here is how I create and fill my x, y, z arrays :
float *x, *y, *z;
x = malloc(sizeof (float) * size);
y = malloc(sizeof (float) * size);
z = malloc(sizeof (float) * size);
for (int i = 0; i < size * split; i++)
x[i] = step * i;
for (int i = 0; i < size * split; i++)
y[i] = step * i;
for (int i = 0; i < size * split; i++)
z[i] = step * i;
It's still very basic, and finally here is the function printing the coordinates in the file, following the vtk legacy format :
void print_Coordinates(FILE *file, float *x, float *y, float *z, int size, int split)
{
fprintf(file, " <Coordinates>\n");
for (int i = 0; i < 3; i++)
{
const char *text1 = " <DataArray type=\"Float32\" Name=\"";
const char *text2 = "\" format=\"ascii\">\n";
fprintf(file, "%s%c%s", text1, 'x' + i, text2);
for (int j = 0; j < size; j++)
{
if (i == 0)
fprintf(file, " %f\n", x[j]);
else if (i == 1)
fprintf(file, " %f\n", y[j]);
else
fprintf(file, " %f\n", z[j]);
}
fprintf(file, " </DataArray>\n");
}
fprintf(file, " </Coordinates>\n");
}
So, yeah, it doesn't do what I want at all.
Here is a screenshot of the result :
All the cubes are on top of each other. With the code I was using earlier, I had several cubes (one per file), but they were aligned on a diagonal (which is not good either).
As you have admitted, there are some problems with your data structure:
The first dimension s seems incongruent: Should the data structure include the original and the smaller cube? That's not easy to do, because the smaller cubes have other dimensions.
You have many separate data: The (random) data, the coordinates and the array dimensions. In order to represent the cube, you need to keep track of all of these. I recommend to create a structure to keep the relevant data together.
There isn't anything per se wrong with your approach to represent the three-dimensional array with a triple pointer, but the design leads to many fragmented allocations. A multi-dimensional array with constant dimensions is probably better represented as one "flat" memory block.
I suggest two structures:
typedef struct Cube Cube;
typedef struct Axis Axis;
struct Axis {
int n; /* number of values */
float *data; /* graduation values */
};
struct Cube {
Axis *x, *y, *z; /* Axes of the cube */
float *data; /* x-major data */
};
An "axis" stores the values along one of the axes. The cube itself doesn't worry about the axis-related code and just delegates it to its three member axes. A "cube" is your data object. (In the implementation below, the data representation is x-major, meaning the x loop is the outermost, the z loop is the innermost. You can chnage that by swapping the loops.)
If you have a populated cube object, you can the extract sub-cubes by creating a cube of a smaller dimension and copying the relevant data ranges from the axes and from the cube data. If you want to cover the whole cube, you can either extract and write the cubes as you go or store them in an array of cubes, e.g. Cube *small[8] for splitting in half for each direction. (This would be like your original s index, only that each cube may have its own dimension.)
An implementation of this behaviour with an (addmittedly simple) test main is below:
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
typedef struct Cube Cube;
typedef struct Axis Axis;
struct Axis {
int n; /* number of values */
float *data; /* graduation values */
};
struct Cube {
Axis *x, *y, *z; /* Axes of the cube */
float *data; /* x-major data */
};
/*
* Create a new axis with a constant step.
*/
Axis *axis_new(int n, float start, float step)
{
Axis *axis = malloc(sizeof(*axis));
float *p;
axis->n = n;
axis->data = malloc(n * sizeof(*axis->data));
p = axis->data;
while (n--) {
*p = start;
start += step;
p++;
}
return axis;
}
/*
* Destroy and clean up axis
*/
void axis_delete(Axis *axis)
{
if (axis) {
free(axis->data);
free(axis);
}
}
/*
* Write axis in XML format to given file
*/
void axis_write(const Axis *axis, FILE *f, const char *name)
{
float *p = axis->data;
int n = axis->n;
fprintf(f, " <DataArray type=\"Float32\" "
"Name=\"%s\" format=\"ascii\">\n", name);
fprintf(f, " ");
while (n--) {
fprintf(f, " %g", *p++);
}
fprintf(f, "\n");
fprintf(f, " </DataArray>\n");
}
/*
* Create a new axis that is a sub-axis of orig.
*/
Axis *axis_slice(const Axis *orig, int start, int len)
{
Axis *axis = axis_new(len, 0, 0);
memcpy(axis->data, orig->data + start, len * sizeof(*axis->data));
return axis;
}
/*
* Create a cube of zero values for the given axes
*/
Cube *cube_new(Axis *x, Axis *y, Axis *z)
{
Cube *cube = malloc(sizeof(*cube));
int dim = x->n * y->n * z->n;
cube->x = x;
cube->y = y;
cube->z = z;
cube->data = malloc(dim * sizeof(*cube->data));
return cube;
}
/*
* Destroy and clean up cube
*/
void cube_delete(Cube *cube)
{
if (cube) {
axis_delete(cube->x);
axis_delete(cube->y);
axis_delete(cube->z);
free(cube->data);
free(cube);
}
}
float *cube_at(const Cube *cube, int x, int y, int z)
{
int pos = (x * cube->y->n + y) * cube->z->n + z;
return cube->data + pos;
}
/*
* Populate all x, y, z values according to the function func.
*/
void cube_populate(Cube *cube, float (*func)(float x, float y, float z))
{
int i, j, k;
float *p = cube->data;
for (i = 0; i < cube->x->n; i++) {
float x = cube->x->data[i];
for (j = 0; j < cube->y->n; j++) {
float y = cube->y->data[j];
for (k = 0; k < cube->z->n; k++) {
float z = cube->z->data[k];
*p++ = func(x, y, z);
}
}
}
}
/*
* Write cube to given file.
*/
void cube_write(const Cube *cube, FILE *f)
{
float *p = cube->data;
int n = cube->x->n * cube->y->n * cube->z->n;
fprintf(f, "<PointData Scalars=\"U\">\n");
fprintf(f, " <DataArray type=\"Float32\" Name=\"U\" format=\"ascii\">\n");
while (n--) {
fprintf(f, " %g", *p++);
}
fprintf(f, "\n");
fprintf(f, " </DataArray>\n");
fprintf(f, "</PointData>\n");
fprintf(f, "<Coordinates>\n");
axis_write(cube->x, f, "x");
axis_write(cube->y, f, "y");
axis_write(cube->z, f, "z");
fprintf(f, "</Coordinates>\n");
}
/*
* Create a new cube that is a sub-cube of orig.
*/
Cube *cube_slice(const Cube *orig,
int x, int dx, int y, int dy, int z, int dz)
{
Cube *cube;
float *p;
int i, j, k;
if (x + dx > orig->x->n) return NULL;
if (y + dy > orig->y->n) return NULL;
if (z + dz > orig->z->n) return NULL;
cube = cube_new(
axis_slice(orig->x, x, dx),
axis_slice(orig->y, y, dy),
axis_slice(orig->z, z, dz));
p = cube->data;
for (i = 0; i < dx; i++) {
for (j = 0; j < dy; j++) {
for (k = 0; k < dz; k++) {
*p++ = *cube_at(orig, x + i, y + j, z + k);
}
}
}
return cube;
}
/*
* Example appliaction
*/
float dist2(float x, float y, float z)
{
return x*x + y*y + z*z;
}
int main()
{
Cube *cube = cube_new(
axis_new(4, 0, 0.1),
axis_new(4, 0, 0.1),
axis_new(4, 0, 0.1));
int i, j, k;
cube_populate(cube, dist2);
for (i = 0; i < 2; i++) {
for (j = 0; j < 2; j++) {
for (k = 0; k < 2; k++) {
Cube *sub = cube_slice(cube, 2*i, 2, 2*j, 2, 2*k, 2);
cube_write(sub, stdout);
printf("--\n");
cube_delete(sub);
}
}
}
cube_delete(cube);
return 0;
}
Having the following code, how can I have "get" receive a map, and return the value at the specified position?
I am attempting to write a cellular automaton in C to try to wrap my head around pointers and memory allocation. Everything was fine until I decided to make "get" to obtain data instead of a direct map[x+world.w*y] as I used to.
I require this because in the future, I plan to have two maps of the same size, and use the same function to get data from them (so it'd be "get(&map2, x, y)" instead of "get(&map, x, y)".
I do this because I was advised against using globals, so I will keep the two maps in main and send their addresses to functions to process.
This is C language, so no C++ solutions are valid.
I tried to search for this in google but all documentation is extremely technical and convoluted, and I am not sure of how this procedure is actually named... So, can anyone help me with this? How can I pass a malloc'ed array to a function and retrieve or alter data from it?
typedef struct Map {
int HP;
int type;
unsigned int flags;
} Map;
typedef struct World {
int w;
int h;
} World;
struct World world;
int tile (int x, int y) { return x + world.w * y; }
int get (/*unknown*/map , int x, int y){
int val = x + world.w * y;
return /*unknown ->?*/ type;
}
int main (){
Map* map;
world.w = 8;
world.h = 8;
int tiles = world.w * world.h;
map = (Map*)malloc(sizeof(Map) * tiles);
int i;
for(i = 0; i < tiles; i++){
map[i].type = rand()%2;
}
int x,y;
while(1){
put(0,0);
for(y = 0; y < world.h; y++){
printf("\n");
for(x = 0; x < world.w; x++){
printf("%i ", get(&map, x, y));
}
}
};
printf("\n");
return 0;
}
Instead of:
get(&map, x, y)
in which you pass the address of the address of the map pointer that malloc() returned, just pass the address itself:
get(map, x, y)
AFAICT from your code, malloc( ) returns exactly the thing that get( ) is looking for, i.e., a pointer to someplace in memory that has room for 64 tiles. So get( ) could look something like:
int
get( Map *map, int x, inty ) {
int val = x + map->w * y; // map is a pointer to struct, not the struct itself
return val; // get( ) returns an int, and it's in val
}
That might be closer to what you want.
-- pete
There are a few other errors in your code, too, but this might let the compiler get off the ground.
Your map variable in main() is already a Map * so don't create a double-indirect pointer out of it by appling & to it at the call site.
Also, int get(Map *m, int x, int y) { ... return map[...]; }
Don't cast the return value from malloc(3).
I may be wrong but from reading your question, it doesn't sound like you are really looking for a function pointer, rather a pointer to a Map structure to pass to a function. Perhaps you want to return a pointer to a particular Map element as well. If this is the case it would look something like the following:
typedef struct Map {
int HP;
int type;
unsigned int flags;
} Map;
typedef struct World {
int w;
int h;
} World;
struct World world;
int tile (int x, int y) { return x + world.w * y; }
Map * get (Map *map , int x, int y){
return map[x + world.w * y];
}
int main (){
Map *map;
Map *m;
world.w = 8;
world.h = 8;
int tiles = world.w * world.h;
map = (Map*)malloc(sizeof(Map) * tiles);
int i;
for(i = 0; i < tiles; i++){
map[i].type = rand()%2;
}
int x,y;
while(1){
put(0,0);
for(y = 0; y < world.h; y++){
printf("\n");
for(x = 0; x < world.w; x++){
m = get(map, x, y); // map was already declared as a pointer
printf("%d\n", m->HP);
printf("%d\n", m->type);
printf("%X\n", m->flags);
}
}
};
printf("\n");
return 0;
Passing a pointer to a struct (or union) in C is easy:
typedef struct Foo
{
int a ;
char b[32] ;
} FOO ;
void do_something_with_a_foo( FOO* p )
{
// using the arror operation '->' to deference a structure pointer
int m = p->a ;
char n = p->b[3] ;
// using the * operator to deference a structure pointer
int x = (*p).a ;
char y = (*p).b[3] ;
return ;
}
void pass_a_foo_pointer_to_function()
{
FOO stack_instance = { 3 , "hello, world" , } ;
FOO* heap_instance = malloc( sizeof(FOO) ) ;
heap_instance->a = 12 ;
strcpy( heap_instance->b , "this, that and the other" ) ;
do_something_with_a_foo( &stack_instance ) ;
do_something_with_a_foo( heap_instance ) ;
free( heap_instance) ;
return ;
}
Cheers!