How to dynamically allocate a struct containing multiple arrays? - c

I'm trying to make a struct that contains another struct with multiple arrays. I need to dynamically allocate those arrays too, so I think I need another pointer still.
int arraysize;
typedef struct Array{
int *size = arraysize;
unsigned int val[*size];
unsigned int x[*size];
unsigned int y[*size];
} Array;
typedef struct Image{
int height;
int width;
int max;
Array *data;
} Image;
OK, so once I finally figure that out, I still need to figure out how to dynamically allocate that memory using malloc. I'm totally lost there too. Any help at all would be greatly appreciated.
EDIT: more clarification:
I'm using the arrays to store three pieces of information that are all connected. Think of a chessboard, you could say knight E4, which tells you that on the 4th column of row E, there is a knight. If you started this process at A1 and ended at K10 you'd have a full chessboard right? The image struct is analogous to the chessboard, the Array is analogous to a list of a bunch of squares that compose the chessboard and the contents of those squares. (E.g. A1 null A2 knight a3 bishop etc...) Unfortunately, I don't know what kind of board will be passed through, it might be a 3x7 board or a 9x2 board etc. So I need to dynamically allocate the memory for those possibilities. Once I have the memory allocated I need to store information about the location and the contents of all of the "squares." Then I need to let a program pass through the height of the board, width of the board and the list of contents and I'd be done the hard part.

What you actually meant was:
typedef struct data {
unsigned int x;
unsigned int y;
unsigned int val;
} Data;
typedef struct image {
int height;
int width;
int max;
Data* data;
} Image;
and somewhere:
Image i;
i.height = 10;
i.width = 20;
i.data = malloc(sizeof(Data) * i.width * i.height);
...
// one of the ways how to access Data at 2nd row, 3rd column:
*(i.data + i.width * 1 + 2).val = 7;
...
free(i.data);
i.data = NULL;
But what you actually need is some good book ;)

Related

Assign value to 2d array of struct in C

I want to create the game 2048 in C, I have a few structs to achieve this:
typedef struct Board {
unsigned int size;
Cell ***cells;
} Board;
typedef struct Cell{
unsigned int value;
} Cell;
The structs are given as a homework, so I cannot change them
What I want to do now is initialize the Board and put one value into it:
Board* create_board(const unsigned int size){
Cell ***cell = (Cell***)malloc(sizeof(Cell *) * size * size);
Board *myboard = {size, cell};
Cell c1 = {2048};
myboard.cells[0][0] = c1; //I need help in this line
return myboard;
}
I am just learning C and pointers are still a little confusing for me, especially if there are 3 * in a row. How do I go about assigning values to a triple pointer array inside a struct?
Any help is appreciated, it was very hard for me to find information online about this kind of problem.

Pointer inside a structure not changing when passing by reference C

So, I'm pretty new to the C language and I've been passed a project by my professor to make a game in C. My problem is, I created a structure like so:
typedef struct vector
{
int parts;
int dir;
} Vector;
typedef struct snake
{
Vector* parts;
Vector dir;
} Snake;
I'm trying to initialize the parts pointer within this function:
void init_snake(struct snake *snake, int size, int x, int y)
{
snake->parts = (Vector *)malloc(sizeof(Vector) * size);
for (int i = 0; i < size; i++)
{
//sets the body parts one after the other in a line
snake->parts[i].x = x - i * PIXEL_SIZE;
snake->parts[i].y = y;
}
//sets the snake direction to the left
snake->dir.x = 1;
snake->dir.y = 0;
}
But by doing that the array parts inside the snake pointer is not initialized as expected. By checking its size with sizeof(snake.parts) / sizeof(Vector) it returns 0. Any ideas of how to fix it?
It likely is working, you're just confused about sizeof. This operator measures the size (in bytes) of a type. If you ask for the size of a value, it uses the type of that expression instead.
This is a compile-time evaluation and therefore is not dynamic.
sizeof(snake.parts) is the same as sizeof(Vector*) which will be either 4 or 8 bytes depending on whether you are compiling to a 32-bit or 64-bit target. Therefore, it's not useful to determine the size of an allocation.
Generally, given a pointer, you cannot tell how large the allocation is. Usually this is handled by storing some kind of useful length somewhere else. For example, you could modify struct snake to include an element count for parts:
typedef struct snake
{
Vector* parts;
int parts_size;
Vector dir;
} Snake;
And set this value accordingly:
snake->parts = (Vector *)malloc(sizeof(Vector) * size);
snake->parts_size = size;

Updating a 2d integer array in a struct with a pointer

I'm trying to implement a coordinate system for a player in a game.
I have a struct
typedef struct player {
int playerPosition[1][5];
}
I create a pointer to that struct
struct* player playerPtr;
struct player playerOne;
playerPtr = &playerOne;
If during the game, I want to update the coordinate of the player to position [1,2].
I get errors when I use playerPtr->playerPosition=[1][2];
What's the correct way of doing this?
As written, you could do this:
playerPtr->playerPosition[0][2] = 100;
But probably you have an error here:
int playerPosition[1][5];
Because it rarely makes sense to have an array of size 1. Did you really mean for playerPosition to be a 1x5 array of ints? It looks like you wanted something like this:
struct position {
int x, y;
};
struct player {
position playerPosition;
};
Then you would do this:
playerPtr->playerPosition.x = 1;
playerPtr->playerPosition.y = 2;
playerPtr->playerPosition=[1][2]; will give you error (syntactically wrong)
you are not specifying the array index at which the data is to be stored, also you cant store data by that way in C.
correct way would be:
playerPtr->playerPosition[0][0] = 1;
playerPtr->playerPosition[0][1] = 2;
.
.
.
playerPtr->playerPosition[9][0] = 19;
playerPtr->playerPosition[9][1] = 20;
which is valid if you declare your array like this:
int playerPosition[10][2];
which will allow you to store ten coordinates.
2Dimentional arrays such as array[1][10] are same as array[10] (for usage, I am not certain about memory allocation, 2D array might require more memory)
I think you could use different but easier approach to this problem:
typedef struct position{
int x, y;
float refpos; //position from some reference point (like healing circle)
}position;
typedef struct player{
char name[20];
int health, attack, defense; //can be float too
position coord[20];
}player;
player player1, *playerPtr;
playerPtr = &player1;
playerPtr->position[0].x = 3;
playerPtr->position[0].y = 4;
playerPtr->position[0].refpos = 5; //Pythagorean triplet wrt origin (0,0)
Prost !

How to fix allocated memory from a struct hack in a different method?

I'm developing a driver in C for communication and the messages exchanged don't have a fixed size. The recommendation of communication bus is to use structs for multi-topics, which is also my case.
My 1st problem: I have to keep listening for new messages, and when I get one I have to process message data (it has a delay) and still listening for new messages.
1st solution: using thread when got new messages to process data.
My 2nd problem: Data in message can have multiple data of a struct, and my communicator requires using a struct to organize this multiple values.
2nd solution: using struct hack to allocate memory dynamic size of struct.
My current problem: when I'd pass my struct as argument to the thread, or any function, I'm loosing data structure and getting wrong values.
A short test which a made is:
typedef struct test{
int size;
int value[];
} test;
void allocation(test *v){
test *aux = (test *)malloc(sizeof(test)+3*sizeof(int));
int i;
aux->value[0] = 2;
aux->size = 3;
aux->value[1] = 1;
aux->value[2] = 5;
printf("Teste1 %d\n",aux->size);
for(i=0; i < aux->size; i++){
printf("%d\n", aux->value[i]);
}
*v = *aux;
}
void cleanup(test *v){
free(v);
}
int main(int argc, char *argv[]){
test v;
int i;
allocation(&v);
printf("Teste2 %d\n",v.size);
for(i=0; i < v.size; i++){
printf("%d\n", v.value[i]);
}
//cleanup(&v);
return 0;
}
In this test I got right values in first print and wrong values in second (only v.size is giving a right value).
And my struct is a little more complex than that in test. My struct is like:
typedef struct test1{
double v1;
double v2;
} test1;
typedef struct test2{
int size;
test1 values[];
} test2;
Do you know how to fix my memory struct in that function, once I have all elements necessary to fix? Please, keep in mind that is desirable (not required) that I could also allocate multiple test2 data.
The thing here is that you assign structs with incomplete member int value[]; Though it is in principle OK to copy two structs by value (and this is actually what happens if you write *v = *aux); However, as the compiler does not know which size member value[] will take on at runtime, the "sizeof" of v as well as the size of *aux is always 4, i.e. the known size of the one int member size. Hence, only this is copied, whereas the value[]-array simply gets not copied.
A way out out this situation would be require a pointer to a pointer (i.e. allocation(test **v), such that the memory reserved can be directly assigned to it, using a pointer to struct test in main, i.e. test *vptr, and call allocation(&vptr).
If you cannot avoid passing a reverence to the value (instead of a reference to a pointer to the value), I suppose you'll have to use memcpy to transfer the contents. But this does actually not make sense, because then the receiver must provide enough space to take on the value[]-array in advance (which is not the case if you simple declare a variable of the form test v). An then the malloc and the aux would make no sense; you could directly write into object v passed by reference.
You are declaring v as non-pointer, meaning that the memory is already allocated for v when you declare it in main. Sending the reference to your allocation only copies the size correctly since it is not dynamically allocated. Correct way to do this would be to:
Declare your v as pointer
Make your allocation return test* (test* allocation())
Assign it to v in main. i.e. something like v = allocate()
And use v like a pointer from then on
EDIT: Since OP wants this to work only as arguments, best way to go about it is using double pointer. Check the following code:
typedef struct test{
int size;
int value[];
} test;
void allocation(test **v){
test *aux = (test *)malloc(sizeof(test)+3*sizeof(int));
int i;
aux->value[0] = 2;
aux->size = 3;
aux->value[1] = 1;
aux->value[2] = 5;
printf("Teste1 %d\n",aux->size);
for(i=0; i < aux->size; i++){
printf("%d\n", aux->value[i]);
}
*v = aux;
}
void cleanup(test *v){
free(v);
}
int main(int argc, char *argv[]){
test **v;
v = malloc (sizeof (test*));
int i;
allocation(v);
printf("Teste2 %d\n",(*v)->size);
for(i=0; i < (*v)->size; i++){
printf("%d\n", (*v)->value[i]);
}
//cleanup(&v);
return 0;
}
Please note that your cleanup will change too after this.

Is there a better way to store pairs of ints?

I'm sorry if this is very basic but I'm still learning all that things I can do in C and can't figure out how to do this.
I create pairs of ints in a program and then need to store them. The way I have been doing it so far is by creating a struct:
struct list_el {
short *val; //first value
short *val2; //second value
struct list_el * next;
};
typedef struct list_el item;
I can iterate though the list fine in my normal program but I want to send this to Cuda and am not sure how to transfer the whole struct into Cuda(I know I can make a reference to it). I'm wondering if there's another way I can structure this data so maybe its array? The format I need is in is just simple pairs (something like this 10:5, 20:40, etc..). I thought worst case I can use a char string and have the pairs as characters and then parse them once the main array is in Cuda but I'm wondering if there's a better way create this list of list?
Assuming that you can use two separate arrays, and thinking about how to use/read/write them in CUDA, I will arrange the data in two arrays mainly due to coalesced accesses from global memory wihtin a kernel.
int *h_val1, *h_val2; // allocate arrays in the host and initialize them
Let be N the size of the arrays, allocate the arrays in device memory
int *d_val1, *d_val2;
cudaMalloc( (void**) &d_val1, N * sizeof(int) );
cudaMalloc( (void**) &d_val2, N * sizeof(int) );
and copy data from host to device memory
cudaMemcpy(h_val1, d_val1, N * sizeof(int), cudaMemcpyHostoToDevice);
cudaMemcpy(h_val2, d_val2, N * sizeof(int), cudaMemcpyHostoToDevice);
Configure and launch your kernel to run as much threads as element in the array.
// kernel configuration
dim3 dimBlock = dim3 ( BLK_SIZE, 1, 1 );
dim3 dimGrid = dim3 ( (N / BLK_SIZE) + 1 );
yourKernel<<<dimGrid, dimBlock>>>(d_val1, d_val2);
With this in mind, implement your kernel
__global__ void
yourKernel(int* val1, int* val2, N)
{
// map from threadIdx/BlockIdx to index position
int gid = threadIdx.x + blockIdx.x * blockDim.x;
if (gid < N)
{
int r_val1 = val1[ idx ]; // load from global memory to register
int r_val2 = val2[ idx ]; // load from global memory to register
// do what you need to do with pair val1:val2
}
}
Do not forget to check for errors when calling CUDA functions.
Instead of storing something that references two ints, store something that holds a copy of the ints.
struct list_el {
int val; //first value
int val2; //second value
struct list_el * next;
};
typedef struct list_el item;
Sometimes it is preferable to hold a reference, sometime it is preferable to hold a value. Depending on what you are attempting to do, use the right tool for the job.
By the way, your reference holding struct was only holding references to shorts. To really hold references to ints, you need
struct list_el {
int *val; //reference to first value
int *val2; //reference to second value
struct list_el * next;
};
typedef struct list_el item;
Note that if you hold a reference, the rest of your program should not dispose of the reference's memory before you dispose of the struct reference to prevent accessing memory that is no longer associated with the program (which is an error).
There are other techniques, if you don't want to use list like constructs.
int val[2] = { 1, 2 };
will store two ints, but only two ints.
int val[2][9];
will store nine pairs of two ints, and could easily also be represented as
int val[9][2];
And of course, there is the old standby
int val = 3;
int val2 = 4;
How about just using a two-dimensional array?
int pairs[30][2];
pairs[0][0] = 10;
pairs[0][1] = 5;
// etc.
I'd have to test it, but I think I tested it, and you can even do something like
int pairs[][2] = {{10, 5}, {20, 40}, ...};
for initialization.
NOTE: This method works well if you know how many pairs you will have ahead of time and the number doesn't grow/shrink (in large amounts). If you have a widely variable number of pairs, sticking with a list of structs and using Edwin's answer would probably be better in the long run.
Having a two dimensional array is a good solution, but I am going to answer as if you are keeping your struct solution.
There's nothing wrong with your storing the short ints in a struct, but I would not store the values in short *. To me it is not worth dynamically allocating memory as you need a new structure.
You could have an array of structs to store this data. Here is an example of a fixed size array of item.
#include <stdio.h>
struct list_el {
short val; //first value
short val2; //second value
};
typedef struct list_el item;
item listA[20];
int main()
{
listA[0].val = 1;
listA[0].val2 = 2;
printf("\n%i %i\n", listA[0].val, listA[0].val2);
return 0
}
Even if you make the argument that you won't know in advance how many of these
structs you will have, I would only allocate space for the array like this:
#include <stdio.h>
#include <stdlib.h>
struct list_el {
short val; //first value
short val2; //second value
};
typedef struct list_el item;
item * p_list_el, * pCurStruct;
int main()
{
int idx;
/* p_list_el is the pointer to the array. Don't modify.
pCurStruct can be modified to walk the array. */
p_list_el = malloc(sizeof(item) * 20);
for(idx=0, pCurStruct=p_list_el; idx < 20; idx++)
{
pCurStruct[idx].val = idx;
pCurStruct[idx].val2 = idx + 1;
}
for(idx=0, pCurStruct=p_list_el; idx < 20; idx++)
{
printf("\n%i %i\n", pCurStruct[idx].val, pCurStruct[idx].val2);
}
free(p_list_el);
}

Resources