I understand I'm splitting the array over the double pointer, but how can I deallocate if I lost the data track?
#include <stdio.h>
#include <stdlib.h>
#define width 20
#define height 20
void allocate_matrix(int ***matrix)
{
double **local_matrix, *data;
local_matrix = (double **)malloc(sizeof(double *) * height);
data = (double *)malloc(sizeof(double) * width * height);
for (int i = 0; i < height; i++)
{
local_matrix[i] = &(data[i * width]);
}
*matrix = local_matrix;
}
void deallocate_matrix(int **matrix) {
}
int main(void) {
int **matrix;
allocate_matrix(&matrix);
deallocate_matrix(matrix);
return 0;
}
You didn't lose track of the second pointer. If you look at your loop body:
local_matrix[i] = &(data[i * width]);
When i is 0, local_matrix[0] is assigned &data[0] which is the same as data. So that's what you need to free:
void deallocate_matrix(int **matrix) {
free(matrix[0]);
free(matrix);
}
First of all, you are allocating space for double then use it as int, which doesn't make sense (and will not compile).
But the main problem here is that you shouldn't be allocating this as fragmented segments but as a contiguous 2D array. Please study Correctly allocating multi-dimensional arrays. This will give a major performance boost and may (arguably) make the code a bit easier to read as well.
If we follow the advise in that post, then your code could be rewritten as:
#include <stdio.h>
#include <stdlib.h>
void allocate_matrix(size_t height, size_t width, int (**matrix)[height][width])
{
int (*local_matrix) [height][width];
local_matrix = malloc(sizeof *local_matrix);
if(local_matrix == NULL)
{
// handle errors
}
*matrix = local_matrix;
}
int main (void)
{
const size_t height = 20;
const size_t width = 20;
int (*matrix)[height][width];
allocate_matrix(height, width, &matrix);
int(*pmatrix)[width] = *matrix; // pointer to first 1D array for easier syntax
for(size_t h=0; h<height; h++)
{
for(size_t w=0; w<width; w++)
{
pmatrix[h][w] = h+w; // assign some sort of data
printf("%d ", pmatrix[h][w]);
}
printf("\n");
}
free(matrix);
return 0;
}
As you can see this also eliminated the need for a complex deallocation routine, since we can just pass the pointer directly to free() and deallocate everything at one single place.
the following proposed code:
needs the header file: stdlib.h for the prototypes for exit() and malloc() and EXIT_FAILURE
performs the desired functionality
you might want to modify the calculation of the initialization values of the matrix
and now, the proposed code:
double **allocate_matrix(void)
{
local_matrix** = malloc( sizeof(double *) * height );
if( ! local_matrix )
{
perror( "malloc for matrix height failed:");
exit( EXIT_FAILURE );
}
for( size_t y = 0; y<height; y++ )
{
local_matrix[y] = malloc( sizeof(double) * width );
if( !local_matrix[y] )
{
//cleanup and exit
}
for ( size_t i = 0; i < width; i++)
{
local_matrix[y][i] = i;
}
}
return local_matrix;
}
int main( void )
{
double **matrix;
matrix = allocate_matrix();
for( size_t y= 0; y< height; y++ )
{
free( matrix[ y ] ):
}
free( matrix );
}
Related
Can anyone explain what is the wrong of print() function ?
printf("Control") never works, output is segmentation fault-11
int main(int argc, char **argv){
int m=5,n=4; // matrix[5][4]
int a=50,b=20; // range: 20-50
int **matrix;
imatrix(matrix,m,n,a,b);
print(matrix,m,n);
first step: filling address with value
void imatrix(int **matrix,int m,int n,int max, int min){
srand(time(NULL));
int i=0,j=0;
matrix = (int **)malloc( m * sizeof(int*) );
if( matrix == NULL ){
printf( "memory req.!" );
}
for( i = 0; i < m; i++ ) {
matrix[i] = (int *)malloc( n * sizeof(int) );
if( matrix[i] == NULL ){
printf( "memory req.!" );
}
}
for(i=0;i<m;i++){
for(j=0;j<n;j++){
matrix[i][j]=(rand()%(max-min))+min;
printf("%2d ",matrix[i][j]);
}
printf("\n\n");
}
}
Anything is okey till here.
I get Segmentation fault: 11 after below code and line of "Control" never works
void print(int **matrix, int m, int n){
int i,j;
for(i=0; i < m; i++){
for(j=0; j < n; j++){
printf("%d",*(*(matrix + i) + j));
}
printf("\n");
}
printf("control");
}
It's not the printf("control") which segfaults (although you'd be a lot better off not using printf for that: consider changing it to puts("control"), which also outputs a newline character.) It's the previous attempt to print the matrix, which is dereferencing an uninitialised value.
That happens because your imatrix function does not return the matrix it created, and the matrix in your main is not given any value.
In fact, imatrix doesn't return anything, since it is defined as returning void. It takes a matrix argument, which I suppose was intended to be an output parameter, but:
that parameter has the wrong type to be an output parameter (an output parameter needs to be a pointer to the object to be returned;)
it never attempts to use the pointer to the object to be returned in order to return the object.
In order to comply with those requirements, you'd need the prototype
void imatrix(int*** matrix, int m, int n, int max, int min);
And you would have to add an additional level of indirection for each usage of matrix [Note 1]:
*matrix = malloc(m * sizeof(**matrix));
if (*matrix == NULL) {
printf( "memory req.!" );
/* NOTE: You shouldn't attempt to continue after the malloc fails.
* Return immediately and let the caller deal with the malloc failure.
*/
}
for( i = 0; i < m; i++ ) {
(*matrix)[i] = malloc( n * sizeof(*(*matrix)[i])) );
if( (*matrix)[i] == NULL ){
// etc.
I think we can agree that that is a major PITA and not worth the trouble unless necessary.
Personally, I find it less confusing to not use output parameters at all unless strictly necessary. In this case it isn't necessary at all because you can just return the pointer to allocate memory:
/* CHANGE: Prototype */
int** imatrix(int m, int n, int max, int min){
srand(time(NULL)); /* TODO: This initialisation should really be done in main */
int i=0, j=0;
/* CHANGE: matrix is a local variable */
int** matrix = malloc( m * sizeof(*matrix) );
/* CHANGE: Immediate return on malloc failure */
if( matrix == NULL ) {
return matrix;
}
for( i = 0; i < m; i++ ) {
matrix[i] = malloc( n * sizeof(*matrix[i]) );
if( matrix[i] == NULL ){
printf( "memory req.!" );
}
}
for(i=0;i<m;i++){
for(j=0;j<n;j++){
matrix[i][j]=(rand()%(max-min))+min;
printf("%2d ",matrix[i][j]);
}
printf("\n\n");
}
/* CHANGE: matrix is returned */
return matrix;
}
That has a slightly different usage pattern:
int main(int argc, char **argv){
int m=5, n=4; // matrix[5][4]
int a=50, b=20; // range: 20-50
/* CHANGE: imatrix returns the new matrix */
int **matrix = imatrix(m, n, a, b);
/* CHANGE: check for failure */
if (matrix == NULL) {
fprintf(stderr, "%s\n", "imatrix failed to allocate memory.");
exit(1);
}
print(matrix, m, n);
/* TODO: Free the storage allocated for matrix */
}
Notes
Throughout this code, I changed the usage of malloc from:
lvalue = (RedundantCast*)malloc(count * sizeof(FixedType));
to idiomatic C:
lvalue = malloc(count * sizeof(*lvalue));
The explicit cast of the return value of malloc is at best pointless in C, since malloc returns a void* and C is happy to automatically convert a void* into a pointer of any type. Using the type of the object pointed to by the target (sizeof(*lvalue)) rather than inserting a specific type protects you against the possibility that the type will change in a future edit, and you forget to make that change in all calls to malloc. (Consider what would happen if you decided to make matrix a matrix of long long instead of int, for example.)
This function should reverse an array of vectors on the heap, but it doesn't work. It seems like the tmp_array also gets changed.
Output is:
13.700000 21.300000
13.700000 21.300000
Should be:
8.900000 31.700000
13.700000 21.300000
createVector creates a struct Vector with two double values x and y.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct _Vector_
{
double x_;
double y_;
} Vector;
Vector *createVector(double x, double y)
{
Vector *vector = malloc((size_t)(sizeof(Vector)));
if (vector == NULL)
{
printf("Memory Error!\n");
return vector;
}
vector->x_ = x;
vector->y_ = y;
return vector;
}
void reverseVectorArray(Vector **vector_array, int length)
{
Vector **tmp_array = malloc(sizeof(Vector*)*length);
if(tmp_array == NULL)
{
printf("Memory Error!\n");
return;
}
memcpy(tmp_array, vector_array, sizeof(Vector*)*length);
int position = length - 1;
for(int i = 0; i<length; i++)
{
*(vector_array[position]) = *(tmp_array[i]);
position--;
}
free(tmp_array);
}
int main()
{
int length = 2;
Vector **vector_array = malloc(sizeof(Vector*) * 2);
vector_array[0] = createVector(13.7, 21.3);
vector_array[1] = createVector(8.9, 31.7);
reverseVectorArray(vector_array, length);
for(int i = 0; i<length; i++)
{
printf("%f ", vector_array[i]->x_);
printf("%f ", vector_array[i]->y_);
printf("\n");
}
return 0;
}
It seems you mean the following.
#include <stdio.h>
#include <stdlib.h>
typedef struct Vector
{
double x;
double y;
} Vector;
Vector * createVector( double x, double y )
{
Vector *vector = malloc( sizeof( Vector ) );
if ( vector )
{
vector->x = x;
vector->y = y;
}
return vector;
}
void reverseVectorArray( Vector **vector_array, size_t n )
{
for ( size_t i = 0; i < n / 2; i++ )
{
Vector tmp = *vector_array[i];
*vector_array[i] = *vector_array[n - i - 1];
*vector_array[n - i - 1] = tmp;
}
}
int main( void )
{
size_t n = 2;
Vector **vector_array = malloc( n * sizeof( Vector * ) );
vector_array[0] = createVector( 13.7, 21.3 );
vector_array[1] = createVector( 8.9, 31.7 );
reverseVectorArray( vector_array, n );
for ( size_t i = 0; i < n; i++ )
{
printf( "%f ", vector_array[i]->x );
printf( "%f ", vector_array[i]->y );
putchar( '\n' );
}
return 0;
}
Take into account that you should append the program with a code that will free all allocated memory.
As for your code then for starters according to the C Standard the function main without parameters shall be declared like
int main( void )
If you are using the function memcpy then you need to include header <string.h>.
Instead of this declaration
Vector *vector = malloc((size_t)(sizeof(Vector*)));
^^^^^^^
you have to write
Vector *vector = malloc( sizeof( Vector ) );
^^^^^^
There is no need to allocate an auxiliary array to reverse the original array. Such an approach is inefficient.
The problem with your function reverseVectorArray is that it rewrites the values of the second half of the array with the values of the first half of the array. So it makes two halves of the array equal each other.
I have a dynamic two - dimensional array , size is height*width.
I want to change array size by using realloc.
This is my code but it is not working.
What should I do? Help me!!
int main(){
char **img;
img = (char**)malloc(sizeof(char*)*height);
for(i=0;i<height;i++){
img[i] = (char*) malloc(sizeof(char)*width);
}
resize(height*2, width*2, img);
}
void resize(int height, int width, char **img){
int i;
img = (char**)realloc(img, sizeof(char)*height);
for(i=0;i<h;i++){
img[i] = (char*)realloc(img[i], width);
}
}
There are two main issues. First, realloc may move the memory block to a new position. Therefore realloc has a return value pointing to either the "old" memory block if no move were necessary, to a new block if a move were necessary, or NULL if an error occurred. Yet you neglect this fact in resize, as it cannot change the pointer object a caller passes in. I'd suggest to adapt the prototype such that resize returns a (probably new) pointer just like realloc does.
Second, when reallocating each row, there might be uninitialized values in the array, probably pointing to "somewhere". Reallocating such an uninitialized value is undefined behaviour. I'd suggest to set the "new" rows to NULL such that realloc can behave correctly afterwards. Therefore it is necessary to know the "old" height, since you have no chance otherwise to distinguish a regularly initialized pointer from a "garbage" pointer.
See the adapted code. Hope it helps.
char** resize(int oldHeight, int oldWidth, int height, int width, char **img){
int i;
img = realloc(img, sizeof(char)*height);
for (int i=oldHeight; i<height; i++)
img[i] = NULL;
for(i=0;i<height;i++){
img[i] = realloc(img[i], width);
for (int col=oldWidth; col < width; col++) {
img[i][col] = 0;
}
}
return img;
}
int main(){
int height = 10;
int width = 20;
char **img;
img = malloc(sizeof(char*)*height);
for(int i=0;i<height;i++){
img[i] = malloc(sizeof(char)*width);
}
img = resize(height, width, height*2, width*2, img);
}
Besides you
are not dealing with a 2D-array and
and the code leak memory if the new height is smaller then the old height and
you do not need to cast void-pointers in C and
all ints should be size_ts
there are two major bugs here, as the code
passes the wrong size to reallocate the outer array. It multiplies height by sizeof (char) instead of sizeof (char*).
misses to initialise the additional pointers realloced to the "outer" array with NULL before passing them to realloc() via the inner resizing-loop.
So the minimal adjustments assuming the new height is greater or equal the old height could look like
void resize(size_t height, size_t height_current, size_t width, char **img){
int i;
img = (char**)realloc(img, sizeof(char*)*height);
for(i=height_current;i<height;i++){
img[i] = NULL;
}
for(i=0;i<width;i++){ // correct copypasta mistake here
img[i] = (char*)realloc(img[i], width);
}
}
A nicer version could look like this
void resize(size_t height, size_t height_current, size_t width, size_t char **img)
{
if (height != height_current)
{
if (height < height_current)
{
for (size_t i = height; i < height_current; ++i)
{
free(img[i]);
}
}
img = realloc(img, height * sizeof *img);
if (height > height_current)
{
for (size_t i = height_current; i < height; ++i)
{
img[i] = NULL;
}
}
}
for (size_t i = 0; i < width; ++i)
{
img[i] = realloc(img[i], width * sizeof *img[i]);
}
}
Call it like this:
resize(height*2, height, width*2, img);
Also you really want to add error checking to all calls to malloc() and realloc() as they might very well fail!
To do this correctly, you must know at least the number of rows before resizing. One possibility is to define a struct containing additional information (kind of OOP approach, have all relevant data together), like the following example (also storing the number of columns, just for completeness, untested code here):
#include <stdlib.h>
#include <string.h>
typedef struct Lookup Lookup;
struct Lookup
{
size_t rows;
size_t cols;
char **data;
};
static void Lookup_destroy(Lookup *self)
{
if (!self) return;
for (size_t r = 0; r < self->rows; ++r)
{
free(self->data[r]);
}
free(self->data);
free(self);
}
static Lookup *Lookup_create(size_t rows, size_t cols)
{
Lookup *self = malloc(sizeof *self);
if (!self) return 0;
self->rows = rows;
self->cols = cols;
self->data = malloc(rows * sizeof *(self->data));
if (!self->data)
{
free(self);
return 0;
}
memset(self->data, 0, rows * sizeof *(self->data));
for (size_t r = 0; r < rows; ++r)
{
self->data[r] = malloc(cols * sizeof *(self->data[r]));
if (!self->data[r])
{
Lookup_destroy(self);
return 0;
}
}
return self;
}
static Lookup *Lookup_resize(Lookup *self, size_t rows, size_t cols)
{
if (!self) return Lookup_create(rows, cols);
// free rows that are no longer needed, if any:
for (size_t r = rows; r < self->rows; ++r)
{
free(self->data[r]);
self->data[r] = 0;
}
// reallocate array of rows:
char **newdata = realloc(self->data, rows * sizeof *newdata);
if (!newdata)
{
Lookup_destroy(self);
return 0;
}
// update row array and row count:
self->data = newdata;
size_t oldrows = self->rows;
self->rows = rows;
// initialize new rows to NULL, if any:
if (rows > oldrows)
{
memset(self->data + oldrows, 0,
(rows - oldrows) * sizeof *(self->data));
}
// reallocate individual rows:
for (size_t r = 0; r < rows; ++r)
{
char *newrow = realloc(self->data[r], cols * sizeof *newrow);
if (!newrow)
{
Lookup_destroy(self);
return 0;
}
self->data[r] = newrow;
}
// update col count:
self->cols = cols;
return self;
}
Note how the result of realloc() is always stored to a temporary variable first, this is needed to correctly handle errors. This code simply throws away the whole object in case of any error -- you can do different things with more code of course.
You could use it in your code like this:
int main(){
Lookup img;
img = Lookup_create(height, width);
// check for NULL here
img = Lookup_resize(img, height*2, width*2);
// and check for NULL here
}
I'm making a program where I have to work constantly with matrices in functions, this is one of the many functions, this function is supposed to take open an external file which is a data set, where the data is separated with tabulations, it opens the file and saves the data in a matrix M, I know this matrix is composed of 6 columns, but the row number is unknown, I know the error is where I declare the matrix, it has to be declared with pointers since the function returns the matrix.
//type float** since it will return a matrix
float **carga_archivo(char *nombre_archivo)
{
float **M=(float **)malloc(6*sizeof(float*)); //error should be here
int i=0;
FILE *archivo; //FILE type pointer to open the external file
archivo=fopen(nombre__archivo,"r"); //Opens the file in the address indicated
//"nombre_de_archivo" is a variable
while(!feof(archivo)) //Browses the file row per row till the end of it
{
//saves the data in its corresponding place in the matrix
fscanf(archivo,"%f\t%f\t%f\t%f\t%f\t%f\n",
&M[0][i],&M[1][i],&M[2][i],&M[3][i],&M[4][i],&M[5][i]);
i++;
}
tam=i;
fclose (archivo); //closes the file
return M;
}
What I need is the right way to declare the matrix.
P.S. I documented the main lines in the code in case it could help someone who needs something similar.
Any correction is welcome.
Update:
Applied some changes proposed in comments, and worked better, here is the new code I nade for that function
float **carga_archivo(char *nombre_archivo)
{
int i=0;
float P[300][6];
FILE *archivo;
archivo=fopen(nombre_archivo,"r");
while(!feof(archivo))
{
i++;
//this was just so the feof function could browse row per row
//instead of character per character
scanf("%f\t%f\t%f\t%f\t%f\t%f\n",
&P[0][i],&P[1][i],&P[2][i],&P[3][i],&P[4][i],&P[5][i]);
printf("%i\n",i);
}
tam=i;
printf("%i",tam);
int filas = 6;
int columnas = tam;
float **M;
M = (float **)malloc(filas*sizeof(float*));
for (i=0;i<filas;i++)
M[i] = (float*)malloc(columnas*sizeof(float));
for (i = 0; i < columnas; ++i)
fscanf(archivo,"%f\t%f\t%f\t%f\t%f\t%f\n",
&M[0][i],&M[1][i],&M[2][i],&M[3][i],&M[4][i],&M[5][i]);
fclose (archivo);
return M;
}
The new problem is when the function is called, the program actually compiles, but when its running and the function is called the program crashes and stops.
Here Is the part of the code that calls to that function.
int main()
{
int i,j;
char *nombre_archivo="Agua_Vapor.txt";
float **agua_vapor=carga_archivo(nombre_archivo);
for (i = 0; i < 6; i++)
{
for (j = 0; i < tam; i++)
printf("%f ", agua_vapor[i][j]);
printf("\n");
}
return 0;
}
Your program has undefined behaviour, because you're populating memory referenced by uninitialised pointers.
Since you know there are always 6 columns, a simple approach is to store the matrix as row-major instead of column-major (your example is column-major). This means you can store the matrix data as one large piece of memory and use realloc when necessary. You may want to make a simple struct for this too.
struct matrix {
int rows, cols;
float ** data;
};
Then create it dynamically.
struct matrix * matrix_alloc( int rows, int cols )
{
int i;
struct matrix * m = malloc(sizeof(struct matrix));
m->rows = rows;
m->cols = cols;
m->data = malloc(rows * sizeof(float*));
m->data[0] = malloc(rows * cols * sizeof(float));
for( i = 1; i < rows; i++ ) {
m->data[i] = m->data[i-1] + cols;
}
return m;
}
void matrix_free( struct matrix * m )
{
free( m->data[0] );
free( m->data );
free( m );
}
Now, when you decide you need to add storage for more rows:
void matrix_set_row_dimension( struct matrix * m, int rows )
{
float **new_index, *new_block;
new_index = realloc(m->data, rows * sizeof(float**));
new_block = realloc(m->data[0], rows * m->cols * sizeof(float));
if( new_index && new_block )
{
int i = m->rows;
m->rows = rows;
m->data = new_index;
/* if block address changed, prepare to reindex entire block */
if( m->data[0] != new_block )
{
m->data[0] = new_block;
i = 1;
}
/* reindex */
for( ; i < rows; i++ ) {
m->data[i] = m->data[i-1] + cols;
}
}
}
So, now as you populate the matrix...
struct matrix * m = matrix_alloc( 10, 6 ); /* Start with 10 rows */
int row = 0;
while( 1 ) {
/* Double matrix row count if not large enough */
if( row == m->rows )
{
matrix_set_row_dimension( m, m->rows * 2 );
/* Check for error here */
}
/* Now the matrix has enough storage to continue adding */
m->data[row][0] = 42;
m->data[row][1] = 42;
m->data[row][2] = 42;
m->data[row][3] = 42;
m->data[row][4] = 42;
m->data[row][5] = 42;
row++;
}
The code works if i use the name of the struct array directly for the allocation, but not from the function argument. Otherwise it returns memory error.
typedef struct COORD
{
int xp;
int yp;
} coord;
coord** xy;
void allocate(coord** COORD)
{
int i;
//allocate COORD[500][460]
COORD = (coord**)malloc(sizeof(coord*)*500);
for(i=0; i<500; i++)
{
COORD[i] = (coord*)malloc(sizeof(coord)*460);
}
// freeing
for (i=0; i<500; i++) free(COORD[i]);
free(COORD);
}
//function call: allocate(xy);
//That is the code that leeds to the error
Using just xy instead of COORD works. And i am all wondering why is that not working.
You are mixing up various coding styles here. It's not clear what exactly you want to achieve. Pick one according to your task.
Temporary buffer
You need a large temporary buffer that should be allocated on the heap and that does not need to be seen from outside. Just create a local variable:
void do_stuff(int w, int h)
{
coord **p;
int i;
p = malloc(h * sizeof(*p));
for (i = 0; i < h; i++) p[i] = malloc(w * sizeof(**p));;
// do stuff
for (i = 0; i < h; i++) free(p[i]);
free(p);
}
Allocate memory for further use
You want to allocate storage that your client code can use. Then provide two functions, one that allocates and one that frees the memory:
coord **create(int w, int h)
{
coord **p;
int i;
p = malloc(h * sizeof(*p));
for (i = 0; i < h; i++) p[i] = malloc(w * sizeof(**p));
return p;
}
void destroy(coord **p, int h)
{
int i;
for (i = 0; i < h; i++) free(p[i]);
free(p);
}
Your client code can then use the memory between these calls:
coord **p = create(500, 460);
// do stuff
drestroy(p, 500);
(Note that you have to pass the height to destroy, which is a bit unfortunate. It might be cleaner to create a wrapper struct that hold information about width and height and the pointer.)
Allocate memory for a global variable
You have a single instance of a global pointer. Then your functions always operate on that pointer and you don't need any further information on it (except the dimensions):
coord **global = NULL;
void destroy_global(int h)
{
int i;
for (i = 0; i < h; i++) free(global[i]);
free(global);
global = NULL;
}
void create_global(int w, int h)
{
int i;
if (global != NULL) free_global();
global = alloc(h * sizeof(*global));
for (i = 0; i < h; i++) global[i] = malloc(w * sizeof(**global));
}
Note that you should include <stdlib.h> for all memory functions and the NULL macro.
Addendum According to your comment, you want to allocate memory for a bitmap. That's option 2 above.
I recommend to create an object structure. You can pass a pointerv to that structure as handle to a bunch of functions. You can create the object with a function that returns that handle.
The following sketches a rough design for a bitmap object.
typedef struct Pixel Pixel;
typedef struct Bitmap Bitmap;
struct Pixel {
uint8_t r, g, b;
};
struct Bitmap {
int height;
int width;
Pixel **pixel;
};
Bitmap *bitmap_new(int w, int h)
{
Bitmap *bmp = malloc(sizeof(*bmp));
int i;
bmp->height = h;
bmp->width = w;
bmp->pixel = malloc(h * sizeof(*bmp->pixel));
for (i = 0; i < h; i++) {
bmp->pixel[i] = malloc(w * sizeof(**bmp->pixel));
}
return p;
}
void bitmap_delete(Bitmap *bmp)
{
int i;
for (i = 0; i < h; i++) free(bmp->pixel[i]);
free(bmp->pixel);
free(bmp);
}
Bitmap *bitmap_read(const char *fn)
{
Bitmap *bmp;
FILE *f = fopen(fn, "rb");
// read and allocate
return bmp;
}
void bitmap_blank(Bitmap *bmp, int r, int g, int b)
{
for (i = 0; i < bitmap->height; i++) {
for (j = 0; j < bitmap->width; j++) {
bmp->pixel[i][j].r = r;
bmp->pixel[i][j].g = g;
bmp->pixel[i][j].b = b;
}
}
}
void bitmap_mirror_x(Bitmap *bmp)
{
// do stuff
}
int bitmap_write(Bitmap *bmp, const char *fn)
{
FILE *f = fopen(fn, "rb");
// write bitmap to file
return 0;
}
The design is similar to the interface to FILE *: fopen gives you a handle (or NULL; error checking is omitted in the code above) and fread, fprintf, fseek and family take a pointer to the file as argument. Finally call fclose to close the file on disk and to free any ressources fopen has claimed.
Have you tried to compile this code? There are a number of errors.
First, the type of main should always be 'int main(int argc, char *argv[])'
Second, you need to '#include <stdlib.h>' at the top of your file to get the return type of malloc/free and friends.
Third, you are not declaring 'i'.
Fourth, you are using the same name 'COORD' as both a struct name and as a variable. Don't do this, it will cause you problems.
Sending incorrect code makes it very difficult to figure out what the root of your problem is, but I suspect it's the overloading of 'COORD'.
typedef struct COORD
{
int xp;
int yp;
} coord;
coord** xy;
void allocate(coord** COORD)
{
int i;
//allocate COORD[500][460]
COORD = (coord**)malloc(sizeof(coord*)*500);
for(i=0; i<500; i++)
{
COORD[i] = (coord*)malloc(sizeof(coord)*460);
}
// freeing
for (i=0; i<500; i++) free(COORD[i]);
free(COORD);
}
//function call: allocate();
//That is the code that works
The problem is that the function allocate() cannot change the value of xy outside itself. This is because C is call by value, the called function only gets the values of its arguments, not any kind of references to the expressions in the caller's context.
It needs to be:
void allocate(coord ***c)
{
}
and:
coord **xy;
allocate(&xy);
which of course is silly: the proper design would be for allocate() to return the new address:
coord ** allocate(void)
{
}
with use like:
coord **xy = allocate();
Probably it would be even better to have the dimensions as parameters to the function, since magic numbers are generally not a good thing:
coord ** allocate(size_t width, size_t height);
typedef struct
{
int xp;
int yp;
} Coord;
Coord **xy;
Coord** allocate(size_t height, size_t width)
{
int i;
Coord **arr;
arr = malloc(sizeof(Coord*)*height);
for(i=0; i<height; i++) {
arr[i] = malloc(sizeof(coord)*width);
}
return arr;
}
void allocate2(Coord ***p_arr, size_t height, size_t width)
{
int i;
Coord **arr;
arr = *p_arr;
arr = malloc(sizeof(Coord*)*height);
for(i=0; i<height; i++) {
arr[i] = malloc(sizeof(coord)*width);
}
}
void deallocate(Coord **arr, size_t height)
{
for (i=0; i<500; i++) {
free(arr[i]);
}
free(arr);
}
int main()
{
Coord **arr_2;
Coord ***p_arr_3;
allocate2(&xy, 500, 460);
/* do something with global array, xy, e.g. */
xy[1][2].xp = 100;
xy[1][2].yp = 200;
deallocate(xy, 500);
arr_2 = allocate(500, 460);
/* do something with local array, arr_2 */
deallocate(arr_2, 500);
allocate2(p_arr_3, 500, 460);
/* do something with ptr to local array, p_arr_3 */
deallocate(*p_arr_3, 500);
return 0;
}