Why can't I return this array? - c

Why am I getting the following errors?
randmst.c: In function ‘main’:
randmst.c:41: error: variable-sized object may not be initialized
randmst.c: In function ‘createGraph’:
randmst.c:84: warning: return from incompatible pointer type
randmst.c:84: warning: function returns address of local variable
createGraph() creates an array of pointers (called VertexPointer) to structs. Once it's created, I'm having trouble passing it back to main().
int main(int argc, char **argv){
//command line arguments
int test = atoi(argv[1]);
int numpoints = atoi(argv[2]);
int numtrials = atoi(argv[3]);
int dimension = atoi(argv[4]);
//perform trials, put results in an array
int i;
int trials[dimension];
for(i = 0; i < numtrials; i++){
VertexPointer graph[numpoint= createGraph(numpoints, dimension);
//testing
int y;
int i;
for(y = 0; y < numpoints; y++){
for(i = 0; i < dimension; i++){
printf("%f \n", (*graph[y]).loc[i]);
}
printf("\n");
}
}
}
//an array of pointers holding the vertices of the graph
VertexPointer
createGraph(int numpoints, int dimension){
//seed the psuedo-random number generator
srand(time(NULL));
//declare an array for the vertices
VertexPointer graph[numpoints];
//create the vertices in the array
int x;
int z;
for(x = 0; x < numpoints; x++){
//create the vertex
VertexPointer v;
v = (VertexPointer)malloc(sizeof(Vertex));
(*v).key = 100;
//(*v).prev = 0;
//multiple dimensions
for(z=0; z < dimension; z++){
(*v).loc[z] = rand_float();
}
//put the pointer in the array
graph[x] = v;
}
return graph;
}

C does not allow you to return arrays. Even if it did, your code declares that createGraph returns a VertexPointer, not an array of them. malloc an array of pointers, change your code to return VertexPointer *, and use a pointer instead of an array in main.
VertexPointer *
createGraph(int numpoints, int dimension) {
...
VertexPointer *graph = malloc(numpoints * sizeof(*graph));
...
return graph;
}
int main(int argc, char **argv) {
...
VertexPointer *graph = createGraph(numpoints, dimension);
...
}

Related

multiple dynamic arrays inside a struct

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++);
}
}
}

Attempt to access elements of a 2d struct array failing

typedef struct{
unsigned long a;
unsigned long b;
unsigned long c;
} mini_struct;
struct ministruct** build_2Dstruct(unsigned long x, unsigned long y){
double x_squared = pow(2, x);
struct ministruct** temp = (mini_struct**)malloc(x*sizeof(mini_struct*));
for(int i = 0; i < x_squared; i++){
temp[i] = (mini_struct*)malloc(y*sizeof(mini_struct));
for(int j = 0; j < y; j++){
temp[i][j].a = 0;
etc....
}
}
return temp;
}
In the code above I am trying to create a 2D array of ministructs**, with the whole struct being made out of 2^x ministructs*, and each ministruct* has y amount of ministructs.
aka:
x = 2,
y = 2,
[[struct, struct], [struct, struct], [struct, struct], [struct, struct]]
However, for some reason when I try to access the second element or index 1 of the struct inside each struct*, it says there is an error: "expression must be pointer to complete object".
I just do not understand why the code is not allowing me to access each individual element of the elements of the array?
Thanks
You are trying to make an x by y array of structs. So:
// create array of x pointers
mini_struct **temp = malloc(x*sizeof(mini_struct*));
for (int i=0; i<x; i++) {
// to array of y structs
temp[i] = malloc(y*sizeof(mini_struct));
for (int j=0; j < y; j++) {
temp[i][j].a = 0;
... etc.
Question is incomplete so I will be making asumptions.
You seem to be wanting to allocate a 2D array of structs and initialize all members to 0. Here is a possible solution:
#include <stdio.h>
#include <math.h>
#include <stdlib.h>
typedef struct mini_struct{
unsigned long a;
unsigned long b;
unsigned long c;
} mini_struct;
struct mini_struct** build_2Dstruct(unsigned long x, unsigned long y){
double x_squared = pow(x, 2);
mini_struct **temp = (mini_struct **) malloc(x_squared * sizeof(mini_struct*));
for(int i = 0; i < x_squared; i++){
temp[i] = (mini_struct *) calloc(y, sizeof(mini_struct));
}
return temp;
}
int main () {
int x = 3;
int y = 4;
mini_struct **struct2D = build_2Dstruct(x, y);
int x_squared = pow(x,2);
for (int i = 0; i < x_squared; ++i) {
for (int j = 0; j < y; ++j) {
printf("Value of data stored at struct[%d][%d] is: %d\n", i, j, struct2D[i][j]);
}
}
for (int i = 0; i < x_squared; ++i) {
free(struct2D[i]);
}
free(struct2D);
}
As you can see, this contains the whole program, not just the snippet you showed. In this case, a main function would have been useful so that we don't have to guess what you want to do. My solution creates the 2D array with all elements initialized to 0 (you can use calloc to do that, no need for a second for loop).
Another important point is that, because the function returns a newly heap allocated 2D array, you need to free it to avoid a memory leak (end of main function).
You allocate x pointers to mini_struct:
mini_struct **temp = (mini_struct **) malloc(x_squared * sizeof(mini_struct*));
But then when you initialize them:
for(int i = 0; i < x_squared; i++){
temp[i] = (mini_struct *) calloc(y, sizeof(mini_struct));
}
You index temp based on upto x_squared.
Consider if x is 2. You would allocate temp to be an array of two pointers to mini_struct. But then your for loop would attempt to initialize four elements in temp.

C: Heap block at ### modified at ### past requested size of ###

So I'm storing a 2D dynamic Array into a matrix struct:
struct Matrix {
int ncol;
int nrow;
double **mat;
};
typedef struct Matrix Matrix;
I then have a function that takes the contents from a 2D array and stores it into the matrix:
// Initializes matrix mat whose values are the passed in 2D array
// Made Matrix **mat a double pointer so that I can initialize the Matrix *pointer from Main
void matrix_initializeFromArray(Matrix **mat, int nrow, int ncol, double array[][ncol]) {
(*mat) = (Matrix*) malloc(sizeof(Matrix*));
(*mat)->mat = (double**) malloc(nrow*sizeof(double*));
for(int i = 0; i < nrow; i++) {
(*mat)->mat[i] = (double*) malloc(ncol*sizeof(double*));
for(int j = 0; j < ncol; j++) { // intialize all values to array values
(*mat)->mat[i][j] = array[i][j];
}
}
(*mat)->ncol = ncol;
(*mat)->nrow = nrow;
}
Where this is the destructor for the matrix:
// Destructor
void matrix_destructor(Matrix **mat) {
for(int i = 0; i < (*mat)->nrow; i++) {
free((*mat)->mat[i]);
}
free((*mat)->mat);
free(*mat);
}
A small example of this is the following:
void main() {
Matrix *temp;
double array[1][1];
array[0][0] = 34;
matrix_initializeFromArray(&temp, 1, 1, array);
matrix_print(temp);
matrix_destructor(&temp);
}
This code executes normally on gdb and valgrind in my Linux Ubuntu but for some reason it creates this error while I run it on Windows.
warning: HEAP[a.exe]:
warning: Heap block at 00B51710 modified at 00B5171C past requested size of 4
I ran through the gdb on Windows and it occurs at this line in the destructor on the first loop: free((*mat)->mat[i]);
Any Help?
I have simplified your code, matrix_print is missing
The issue was with the malloc
when you allocate something you get a pointer to the memory, for example
malloc(sizeof(double)); returns a pointer to a memory area that can store a double so a double *
malloc(sizeof(double*)); returns a pointer to a memory are that can store a pointer to a double, so a double **`
#include <stdio.h>
#include <stdlib.h>
struct Matrix {
int ncol;
int nrow;
double **mat;
};
typedef struct Matrix Matrix;
void matrix_initializeFromArray(Matrix *mat, int nrow, int ncol, double array[][ncol]) {
mat->ncol = ncol;
mat->nrow = nrow;
mat->mat = malloc(nrow * sizeof(double*));
for(int i = 0; i < nrow; i++) {
mat->mat[i] = malloc(ncol*sizeof(double));
for(int j = 0; j < ncol; j++) { // intialize all values to array values
mat->mat[i][j] = array[i][j];
}
}
}
void matrix_wipe(Matrix *mat) {
for(int i = 0; i < mat->nrow; i++) {
free(mat->mat[i]);
}
free(mat->mat);
}
int main(void) {
Matrix temp;
double array[1][1];
array[0][0] = 34;
matrix_initializeFromArray(&temp, 1, 1, array);
matrix_wipe(&temp);
return 0;
}

Struct with variable size of array

I want to save data in arrays called plist. These arrays can vary in size and are part of a structure called ParticleList. I know how to create one list of size n[0]. n[0] for example is of size 2. Thus, a list of size 2. But what do I have to do, if I want to create several lists with size n[0], n[1], n[2] of type ParticleList?
To cut a long story short: How should I modify my code in order to access lists of variable size somehow like pl[numberOfList].plist[PositionInArray] = -1 or `pl[numberOfList] -> plist[PositionInArray] = -1'
#include <stdlib.h>
#include <stdio.h>
typedef struct{
double *plist;
int plistSize;
} ParticleList;
void sendPar(int *n, int nl){
// Allocate memory for struct ParticleList
ParticleList *pl = malloc(sizeof(ParticleList));
// Allocate memory for list
pl->plist = malloc(sizeof(double)*n[0]);
// Fill list with data
for(int k=0; k<n[0]; k++){
pl->plist[k] = -1;
}
// Write size of list into file
pl->plistSize = n[0];
// Print data
printf("Content of list:\n");
for(int k=0; k<n[0]; k++){
printf("%lf\n", pl->plist[k]);
}
printf("Size of list: %d\n", pl->plistSize);
// Free memory
free(pl);
}
int main(){
// Number of lists
int nl = 3;
// Size of lists
int n[nl];
n[0] = 2;
n[1] = 3;
n[2] = 4;
sendPar(n, nl);
}
Do you mean something like this?
typedef struct{
int plistSize;
double* plist;
} ParticleList;
int main()
{
int i, z = 0;
/* Assuming you have three lists with three different sizes */
double list1[2] = {-1.0, -1.1};
double list2[3] = {-2.0, -2.1, -2.2};
double list3[4] = {-3.0, -3.1, -3.2, -3.3};
/* Create an array of three Particle Lists */
ParticleList pl[3] = {{list1, 2},{list2, 3},{list3, 4}};
/* Access the values in the Particle Lists */
for(i = 0; i < 3; i++)
{
printf("ParticleList pl[%i]:\n", i);
for(z = 0; z < pl[i].plistSize; z++)
{
printf("pl[%i].plist[%i] = %f\n", i, z, pl[i].plist[z]);
}
}
/* Change the first item of the second list */
pl[1].plist[0] = 2.3;
}
This way you can access each item in each list by
pl[<index of list>].plist[<index of list item>]
A bit more dynamic by using flexible array members (this way one of the lists can be replaced by another list of different size):
Note that I changed the struct!
typedef struct{
int plistSize;
double plist[];
} ParticleList;
int main()
{
int i, z = 0;
ParticleList *pl[3];
/* Allocate memory for the lists */
pl[0] = malloc( sizeof(ParticleList) + sizeof(double[2]) );
pl[0]->plistSize = 2;
pl[1] = malloc( sizeof(ParticleList) + sizeof(double[3]) );
pl[1]->plistSize = 3;
pl[2] = malloc( sizeof(ParticleList) + sizeof(double[4]) );
pl[2]->plistSize = 4;
/* Write the values in the Particle Lists */
for(i = 0; i < 3; i++)
{
printf("ParticleList pl[%i]:\n", i);
for(z = 0; z < pl[i]->plistSize; z++)
{
pl[i]->plist[z] = -i;
}
}
/* Print the values */
for(i = 0; i < 3; i++)
{
printf("ParticleList pl[%i]:\n", i);
for(z = 0; z < pl[i]->plistSize; z++)
{
printf("pl[%i]->plist[%i] = %f\n", i, z, pl[i]->plist[z]);
}
}
/* Change the first value of the second list */
pl[1]->plist[0] = -1.1;
/* Replace the first list by a new one */
free(pl[0]);
pl[0] = malloc( sizeof(ParticleList) + sizeof(double[5]) );
pl[0]->plistSize = 5;
/* Assign some new values to the new list 1 */
pl[0]->plist[0] = -4.1;
pl[0]->plist[1] = -4.2;
pl[0]->plist[2] = -4.3;
pl[0]->plist[3] = -4.4;
pl[0]->plist[4] = -4.5;
/* Print the values */
for(i = 0; i < 3; i++)
{
printf("ParticleList pl[%i]:\n", i);
for(z = 0; z < pl[i]->plistSize; z++)
{
printf("pl[%i]->plist[%i] = %f\n", i, z, pl[i]->plist[z]);
}
}
/* free all lists before exiting the program */
for(i = 0; i < 3; i++)
{
free(pl[i]);
}
return 0;
}
It would seem you are looking for the language feature called flexible array member. It works like this:
typedef struct{
int plistSize;
double plist[];
} ParticleList;
ParticleList *pl = malloc( sizeof(ParticleList) + sizeof(double[n]) );
pl->plistSize = n;
...
free(pl);
Where n is the size you want plist to have.

Passing struct array of pointers as a function argument?

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;
}

Resources