I have a structure and a bidimensional array of those structs:
typedef struct {
char exit_n;
char exit_s;
char exit_w;
char exit_e;
} room;
room map[MAP_WIDTH][MAP_HEIGHT];
I need an array of pointers those structs. The following code compiles, but I don't get the wanted result. Any help? This is getting really confused to me, any explanation would be appreciated
room *rooms;
rooms = (room*)malloc(sizeof(room*) * ROOM_NUM);
[..]
rooms[n] = map[room_x][room_y];
[..]
Actually, I think you want
room** rooms;
rooms = (room**)malloc(sizeof(room*) * ROOM_NUM);
[..]
rooms[n] = &map[room_x][room_y];
This gives you an array of pointers to your rooms.
I'm am pretty sure you want
sizeof(room)
You need to allocate enough space for the struct. You are only allocating for a pointer.
You also may need to allocate differently if you want a 2D array:
see here dynamic allocating array of arrays in C
The major issue I see is that you are using sizeof(room*). This means that you are taking the size of a pointer to a structure, which is not what you want. You want to allocate the size of the structure, so make that sizeof(room). Also, use calloc in this case, not malloc, as you are basically implementing the former's functionality by multiplying the number of rooms by the size of the room.
In your current code, rooms becomes an array of room structures, not an array of pointers. If you want an array of pointers that each point to your map array, you need another layer of indirection:
room** rooms = malloc(ROOM_NUM * sizeof *rooms);
// ...
rooms[n] = &map[room_x][room_y];
(Or you can use sizeof (room *) like your code has instead of sizeof *rooms; I prefer to write it that way to avoid duplicating type information.)
You need to allocate space for the pointers and for the rooms and then initialize the pointers to point to the rooms.
room *rooms;
room **prooms;
rooms = (room*)malloc((sizeof(room) + sizeof(room*)) * ROOM_NUM);
prooms = (room**)(&rooms[ROOM_NUM]);
for (int ii = 0; ii < ROOM_NUM; ++ii)
prooms[ii] = &rooms[ii];
If I understand correctly, you want an array of pointers to all the room values in map. Since there are MAP_WIDTH*MAP_HEIGHT such values, we need that many pointers:
room *rooms[MAP_WIDTH*MAP_HEIGHT];
The above declares rooms as an array of pointers.
Now, to assign the values:
size_t i;
size_t j;
for (i=0; i < MAP_WIDTH; ++i)
for (j=0; j < MAP_HEIGHT; ++j)
rooms[i*MAP_HEIGHT+j] = &map[i][j];
We basically find the address of each element in map, and store it in the correct entry in rooms.
Is this what you wanted?
Related
This question already has answers here:
Dynamic array in C — Is my understanding of malloc and realloc correct?
(3 answers)
Closed 5 years ago.
So for my school project, a large CSV file will be entered through stdin and we will have to sort it based on column and print it out as a sorted csv file.
The step I am on right now is figuring out how to keep reallocing a struct of arrays so that it will grow if there is not big enough to hold the data coming in from stdin. We don't know the exact amount of rows that will be inputted in the CSV file. Right now we just used a static amount to test and see if the values are assigned to the structs.
I am still a beginner at C so I do not clearly know how I would iterate through a pointer like I would iterate through an array. Since we are using a static amount of structs in the array, we can just iterate using array[i] like in Java but how would you iterate through something like *array?
I do not know where to start for creating this dynamic array. I tried
struct array* testArray = (array*)malloc(sizeof(testArray));
but I have no idea how to iterate through it like I did with the static array by using array[i].
Any help would be greatly appreciated, sorry for the wall of text...
You can navigate through a malloced space the same way as with an array (using indicies), but it seems that your main issue lies in your use of malloc. Malloc's argument is the size in number of bytes that you want to allocate. So if you want to have an array of structs, you would first need to find out how many bytes one struct contains using sizeof(struct array), and then determine how large of an array you want, let's say N. So that line of code should look more like struct array* testArray = malloc(N * sizeof(struct array));. The return value of malloc will be a void pointer containing the memory address of the first byte of allocated space. Upon assigning this value to testArray, it will be type-casted to the assigned variable type (struct array *). Now you can use pointer arithmetic to access a specific index i with *(testArray + i), or simply testArray[i]. If you find that N was not a sufficient size, you can use realloc to increase the array size to 2N, or whatever size deemed necessary.
struct array* testArray = (array*)malloc(sizeof(testArray));
is a little wrong as you only allocate 1 element of testArray.
It is more like:
struct A
{
int a;
int b;
....
};
struct A* arr = malloc( N * sizeof(struct A) );
^^^
N element of struct A
int j;
for (j=0; j<N; ++j) // Iterate it like any other array
{
arr[j].a = 5;
arr[j].b = 42;
....
}
Use realloc when you need the array to grow.
When reading from a file/stdin it could look like (based on comment from David C. Rankin):
int n=0; // Count of the number of structs read from the file
struct A* arr = malloc( N * sizeof(struct A) );
while (read line from file)
{
arr[n].a = val1;
arr[n].b = val2;
++n; // Increment count
if (n == N) // Check if current array is full, i.e. realloc needed
{
// realloc array to 2 * N; N = N * 2
}
}
I am new in whole C programming thing (comming from Java), and honestly its really confusing. Ok to the problem I am trying to allocate contigous chunk of data for my 2D array of strings (Guessing its something like 3D array??). All I have is this i believe contiguous allocation for Array of strings?
Can someone help me out with 2D array please?
And yes I know size before running the program, its defined so ROWS for rows, COLS for columns and NAME for length of string.
char **people = malloc(COLS * sizeof(char *));
people[0] = malloc(COLS * NAME);
for(int i = 1; i < COLS; i++)
people[i] = people[0] + i * NAME;
If you actually know the size of the array before running the program, you don't need to dinamically allocate the memory with malloc, you could create a 2D static array. In your case, as it is a 2D array of strings, it could be declared as char * array[ROWS][COLS], and then you could asign a string to a specific element this way: array[nrow][ncol]="Your String".
C, unlike Java, actually has a concept of multidimensional arrays; so unless there's a specific reason you want a char * * *, you might prefer to write:
char (*people)[COLS][NAME] = malloc(ROWS * sizeof(*people));
which sets people to be a pointer to the first of ROWS dynamically-allocated two-dimensional character arrays.
Due to pointer "decay", where an expression of array type will double as a pointer to the first element of the array, you can use people very much as if it were a char * * *; for example, people[3][4] will point to the string in row 3, column 4. The only restriction is that you can't write something like people[3][4] = ... to suddenly change what string to point to. But it sounds like you don't want to do that, anyway?
Note: the above is assuming that you are intentionally using dynamic memory allocation. However, I do recommend you consider Sizigia's suggestion to use static memory, which is the same sort of storage as is used for global variables. If you write something like
static char people[ROWS][COLS][NAME];
then the memory will be allocated just once, at the start of the program, and reused by all calls to the function that declares it.
You can define a char * using typedef so it's better for you to understand the code. Then all you have to do is to dynamically allocate a 2D array of your defined type (in the example below, I defined it as a "string"):
typedef char * string;
string ** people;
people = malloc(ROWS * sizeof(string));
for(int i = 0; i < ROWS; i++){
people[i] = malloc(COLUMNS * sizeof(char));
}
You can access it using the normal array sintax, people[i][j].
I am using GTK, and I am not sure with malloc() function here. Valgrind gives me a memory leak, what I am doing bad?
at first I create pointer to pointer to pointer to GTK widget, because I need three dimensional array.
GtkWidget*** widgets;
and I am using malloc like this:
widgets = malloc((1)*sizeof(GtkWidget**));
for(i = 0; i<= l-1; i++) // l = 4 in my case
{
widgets[i] = malloc((1)*sizeof(GtkWidget*));
for(j = 0; j<=3; j++) // 4 is number of elements in this dimension
{
widgets[i][j] = malloc((1)*sizeof(GtkWidget));
}
}
and at the end I am doing this:
widgets[0][0] = gtk_menu_item_new_with_label("MyLabel");
gtk_menu_shell_append(GTK_MENU_SHELL(indicator_menu), widgets[0][0]);
my array can be smaller and bigger, so I am using dynamic allocation of array, my maximal array indexes are something like widgets[3][3].
I did not post whole code, because it is pretty long, I sent here just the parts for which was valgrind complaining to. What I am doing bad? thank you.
You're only allocating the size of a pointer, when you mean to allocate an array of pointers.
// this will allocate a single character pointer
char ** ptr = malloc(1 * sizeof(char *));
// this will allocate n character pointers
char ** ptr = malloc(n * sizeof(char *));
So if you want a two dimensional array of dimension NxM, you'll need to allocate an array of size N, then walk through that array from 0 to N-1 and allocate arrays of size M.
What you're doing now is assigning pointers returned from malloc to memory you don't own. Is what you actually want a two-dimensional array of pointers to GtkWidget structures?
Using l as a local variable is not a good idea. It is very easy to make a mistake between l and 1, in some editors they look very much the same.
widgets = malloc((l)*sizeof(GtkWidget**)); //is what you needed
iso
widgets = malloc((1)*sizeof(GtkWidget**));
Over here with syntax highlighting the problem immediately appears.
So another suggestion is to for sure use an editor with syntax highlighting
I plan to create an 2D array of a pointer derived from typedef struct
Let's say the typedef struct is named "Items" and contains mixed variables of strings and integers.
I will declare two intvariables namely typenum and typetotal. These two integers will start off from Zero and adds up when the input data matches with certain function.
In the array,Items *type[][], basically type[][] is Items *type[typenum][typetotal] but I cannot do this since I will declare typenum and typetotal as zero at the declaration part.
I tried initializing the array through Items *type[][] = {{0},{0}} but this generates error.
Any advice? Some told me to use malloc() on this, but I simply do not know how.
*Using Tiny C on Windows
Use dynamic memory allocation.
Items **type;
type = malloc(sizeof (Items *) * typenum);
for (int i = 0; i < typenum; i++)
type[i] = malloc(sizeof Items) * typetotal);
You need to manually free the allocated memory after using the array.
for (int i = 0; i < typenum; i++)
free(types[i]);
free(types);
Here is a tutorial on it: http://www.eskimo.com/~scs/cclass/int/sx9b.html
If typenum and typetotal increase as your program runs be sure to use realloc, which will reallocate more memory and keep the contents. You'll need to allocate the first dimension of the array like this:
myArray = realloc(myArray, sizeof(Items*) * typenum);
and then allocate the second dimension for each of the first:
for(...)
myArray[i] = realloc(myArray[i], sizeof(Items) * typetotal);
I am working with a 2-dimensional array of structs which is a part of another struct. It's not something I've done a lot with so I'm having a problem. This function ends up failing after getting to the "test" for-loop near the end. It prints out one line correctly before it seg faults.
The parts of my code which read data into a dummy 2-d array of structs works just fine, so it must be my assigning array to be part of another struct (the imageStruct).
Any help would be greatly appreciated!
/*the structure of each pixel*/
typedef struct
{
int R,G,B;
}pixelStruct;
/*data for each image*/
typedef struct
{
int height;
int width;
pixelStruct *arr; /*pointer to 2-d array of pixels*/
} imageStruct;
imageStruct ReadImage(char * filename)
{
FILE *image=fopen(filename,"r");
imageStruct thisImage;
/*get header data from image*/
/*make a 2-d array of of pixels*/
pixelStruct imageArr[thisImage.height][thisImage.width];
/*Read in the image. */
/*I know this works because I after storing the image data in the
imageArr array, I printed each element from the array to the
screen.*/
/*so now I want to take the array called imageArr and put it in the
imageStruct called thisImage*/
thisImage.arr = malloc(sizeof(imageArr));
//allocate enough space in struct for the image array.
*thisImage.arr = *imageArr; /*put imageArr into the thisImage imagestruct*/
//test to see if assignment worked: (this is where it fails)
for (i = 0; i < thisImage.height; i++)
{
for (j = 0; j < thisImage.width; j++)
{
printf("\n%d: R: %d G: %d B: %d\n", i ,thisImage.arr[i][j].R,
thisImage.arr[i][j].G, thisImage.arr[i][j].B);
}
}
return thisImage;
}
(In case you are wondering why I am using a dummy array in the first place, well it's because when I started writing this code, I couldn't figure out how to do what I am trying to do now.)
EDIT: One person suggested that I didn't initialize my 2-d array correctly in the typedef for the imageStruct. Can anyone help me correct this if it is indeed the problem?
You seem to be able to create variable-length-arrays, so you're on a C99 system, or on a system that supports it. But not all compilers support those. If you want to use those, you don't need the arr pointer declaration in your struct. Assuming no variable-length-arrays, let's look at the relevant parts of your code:
/*data for each image*/
typedef struct
{
int height;
int width;
pixelStruct *arr; /*pointer to 2-d array of pixels*/
} imageStruct;
arr is a pointer to pixelStruct, and not to a 2-d array of pixels. Sure, you can use arr to access such an array, but the comment is misleading, and it hints at a misunderstanding. If you really wish to declare such a variable, you would do something like:
pixelStruct (*arr)[2][3];
and arr would be a pointer to an "array 2 of array 3 of pixelStruct", which means that arr points to a 2-d array. This isn't really what you want. To be fair, this isn't what you declare, so all is good. But your comment suggests a misunderstanding of pointers in C, and that is manifested later in your code.
At this point, you will do well to read a good introduction to arrays and pointers in C, and a really nice one is C For Smarties: Arrays and Pointers by Chris Torek. In particular, please make sure you understand the first diagram on the page and everything in the definition of the function f there.
Since you want to be able to index arr in a natural way using "column" and "row" indices, I suggest you declare arr as a pointer to pointer. So your structure becomes:
/* data for each image */
typedef struct
{
int height;
int width;
pixelStruct **arr; /* Image data of height*width dimensions */
} imageStruct;
Then in your ReadImage function, you allocate memory you need:
int i;
thisImage.arr = malloc(thisImage.height * sizeof *thisImage.arr);
for (i=0; i < thisImage.height; ++i)
thisImage.arr[i] = malloc(thisImage.width * sizeof *thisImage.arr[i]);
Note that for clarity, I haven't done any error-checking on malloc. In practice, you should check if malloc returned NULL and take appropriate measures.
Assuming all the memory allocation succeeded, you can now read your image in thisImage.arr (just like you were doing for imageArr in your original function).
Once you're done with thisImage.arr, make sure to free it:
for (i=0; i < thisImage.height; ++i)
free(thisImage.arr[i]);
free(thisImage.arr);
In practice, you will want to wrap the allocation and deallocation parts above in their respective functions that allocate and free the arr object, and take care of error-checking.
I don't think sizeof imageArr works as you expect it to when you're using runtime-sized arrays. Which, btw, are a sort of "niche" C99 feature. You should add some printouts of crucial values, such as that sizeof to see if it does what you think.
Clearer would be to use explicit allocation of the array:
thisImage.arr = malloc(thisImage.width * thisImage.height * sizeof *thisImage.arr);
I also think that it's hard (if even possible) to implement a "true" 2D array like this. I would recommend just doing the address computation yourself, i.e. accessing a pixel like this:
unsigned int x = 3, y = 1; // Assume image is larger.
print("pixel at (%d,%d) is r=%d g=%d b=%d\n", x, y, thisImage.arr[y * thisImage.width + x]);
I don't see how the required dimension information can be associated with an array at run-time; I don't think that's possible.
height and width are undefined; you might want to initialise them first, as in
thisImage.height = 10; thisImage.width = 20;
also,
what is colorRGB?
*thisImage.arr = *imageArr; /*put imageArr into the thisImage imagestruct*
This won't work. You have to declare arr as colorRGB **, allocate it accordingly, etc.
it looks like you are trying to copy array by assignment.
You cannot use simple assignment operator to do that, you have to use some function to copy things, for example memcpy.
*thisImage.arr = *imageArr;
thisimage.arr[0] = imagearr[0];
The above statements are doing the same thing.
However this is not most likely what causes the memory corruption
since you are working with two dimensional arrays, do make sure you initialize them correctly.
Looking at the code, should not even compile: the array is declared as one-dimensional in your image structure but you refer to as two-dimensional?