struct with a dynamic memory array element in c - c

I am trying to create a struct. One of the elements of the struct is an array that should be able to grow if needed.
I do this:
int COLS=2, ROWS=20;
long int (*array)[COLS] = malloc(sizeof(int[ROWS][COLS]));
struct test{
long int (*arr)[COLS];
};
struct test *s_test = malloc(sizeof(s_test));
s_test->arr = array;
for (int i=0; i<ROWS; i++){
array[i][0]=i;
array[i][1]=i+20;
printf("0:%ld\t1:%ld\n",s_test->arr[i][0], s_test->arr[i][1]);
}
but the compiler says:
test.c:10:14: error: fields must have a constant size: 'variable length array in structure' extension will never be supported
long int (*arr)[COLS];
This works ok:
int COLS=2, ROWS=20;
long int (*array)[COLS] = malloc(sizeof(int[ROWS][COLS]));
long int (*arr)[COLS];
//struct test{
// long int (*arr)[COLS];
//};
struct test *s_test = malloc(sizeof(s_test));
//s_test->arr = array;
arr = array;
for (int i=0; i<ROWS; i++){
array[i][0]=i;
array[i][1]=i+20;
printf("0:%ld\t1:%ld\n", arr[i][0], arr[i][1]); //s_test->arr[i][0], s_test->arr[i][1]);
}
BTW, I, mistakenly forgot to delete the declaration of a struct test (which is not defined now) and the compiler didn't complain...). I will also appreciate a very simple (if possible) explanation of why.
1 - I clearly don't know how to solve this problem.
2 - Does the struct HAS to be a pointer?
3 - Can't the element arr be a pointer to theh 2darray?
Thank you a lot!

Disclaimer: I think long int (*arr)[COLS] (flexible array to pointer to long) is a mistake; but all you need to do to fix it is adjust the type.
That doesn't look quite right. if COLS really is dynamic we need to say:
struct test{
long int (*arr)[];
};
but this is invalid due to the toy example being too small. The stretchy element has to be the last one, but it can't be the only one either. Needs to look like this:
struct test{
size_t nelem; /* I suppose you could have another way of knowing how many */
long int (*arr)[];
};
and you allocate it with a call that looks like this:
struct test *ptr = malloc(sizeof(struct test) + sizeof (long int *) * COLS);
If COLS is really constant, the way to get to compile is to change the declaration of COLS to be a macro, or an enum like so: enum { COLS = 2; };

Related

Allocating array size inside struct from user input in C

I'm recently working on a project in C. I have a requirement to allocate an array inside a struct and its size need to be obtained from the user. But because of specific requirements, I cannot use pointers and then allocate memory using malloc.
My code is as follows:
#define arraySize size
typedef struct sample{
int keys[arraySize]
int pointers[arraySize + 1]
} sample;
int main(){
//size should be obtained from user input
size = 15;
}
If the struct is defined inside main, it works fine but the issue is then the struct won't be global. If I declare the struct as mentioned in the code it gives the error message stating that the array size needs to be constant. Can anyone help me with this issue?
(Just giving examples for the comments.)
I think there are a few typical ways of handling your scenario:
Method 1: Global pointer to resources allocated on main's stack (already suggested in other comments):
This variant uses the C99 feature / GCC extension (w.r.t C89) for variably-modified types / variably modified arrays, per Jonathan Leffler's comment.
struct sample *globalSample = NULL;
int main(){
//size should be obtained from user input
size = 15;
struct sample{
int keys[size];
int pointers[size + 1];
} mySample;
globalSample = &mySample;
}
This variant uses alloca and "flexible array member". Per Jonathan Leffler's comment below note the change of officially defined syntax for this between C89 and later revisions of the C spec.
struct inner {
int key;
int pointer;
};
struct sample {
unsigned int num_allocated;
struct inner members[1]; // struct hack
};
struct sample *globalSample = NULL;
int main(){
//size should be obtained from user input
size = 15;
globalSample = alloca((size+1) * sizeof(struct sample));
globalSample->num_allocated = size; /*just for book-keeping*/
globalSample->members[0].key = /*...*/;
globalSample->members[0].pointer = /*...*/;
globalSample->members[1].key = /*... reaching past declared size */
globalSample->members[1].pointer = /*...*/;
}
Method 2: Define a max size, and validate user input against it.
#define MAX_ENTRIES 4096
struct sample{
int keys[MAX_ENTRIES];
int pointers[MAX_ENTRIES + 1];
} globalSample;
int main(){
//size should be obtained from user input
size = 15;
if(MAX_ENTRIES < size) { /* error case */ }
}

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.

C struct with array size determined at compile time

How does one build a struct with an array that can be set differently for each struct, ideally by a parameter? The application being a single data type that supports arrays of different, but fixed lengths
My attempt looks somehting like this, which obviously didnt compile:
struct Data_struct(n)
{
int xData[n];
int test;
};
The only method available is to use a flexible array member.
struct Data_struct {
int test;
int xData[];
};
You would then allocate space for this using malloc():
int n = 4;
struct Data_struct *s = malloc(sizeof(struct Data_struct) + n * sizeof(int));
Note that we had to explicitly allocate additional space for the flexible array.
You can dynamically allocate the array
struct Data_struct
{
int * xData;
int test;
};
....
s.xData = calloc(size, sizeof(int))
and remember to free xData when finished
Normally you would define a variable length array at the end of the struct, and then fix up the size at run-time, e.g.
typedef struct
{
int test;
int xData[1];
} Data_struct;
To allocate a struct such as this with a size of n for xData you'd do soemthing like this:
Data_struct * s = malloc(sizeof(Data_struct) + (n - 1) * sizeof(int));
One might call this ugly but here goes. Use a #define
#define foo(n) struct Data_struct##n { int test; int xData[n]; }
foo(20);
struct Data_struct20 abc;
The foo(20) defines a structure with n = 20 characters.
You could use another #define for the allocation of space if you wish.

Changing the size of struct after declared

I have a code contains this structure
struct mystruct{
int a;
int array[1];
};
Directly, after running the code
I mean I will not declare any variable of that structure,the user will enter a number, for example 6.
What I want is to know how I can change the size of that structure.
Like I declared on this form
struct mystruct{
int a;
int array[6];
};
Then I use normally, like this:
struct mystruct var;
//I do not want to add any code here, to appropriate new form
for(int i=0;i<6;i++)
var.array[i]=0;
The typical way to do something like this in straight C (as opposed to C++) is to have just a pointer member in the struct, to point to the array, and then another member of the struct to indicate the size. This generally requires users of the struct to malloc() the array as needed, and to also set the size member to match. Something like:
struct mystruct
{
int size;
int *array;
};
and:
struct mystruct var;
var.array = malloc(6 * sizeof(int));
var.size = 6;
for (int i = 0; i < var.size; i++)
var.array[i] = 0;
Another common paradigm is a linked list.
Of course, in C++ you could just use a std::vector<int>.
You cannot change the declaration of the struct but if it is a variable length array within a struct that you want you do have an option. Declare your struct as:
struct mystruct{
int a;
int array[0];
};
And then when you want to create an instance with n elements in the array do the following:
struct mystruct *a = malloc(sizeof(struct mystruct) + n * sizeof(int));
This will create a memory region large enough to hold the struct and an array of length n. You can then use the array just as you would any other array:
a->array[1] = 5;
(this example assumes the array has at least 2 elements)
To accomplish what you have in your code example you would want to do something like this:
struct mystruct *var = malloc(sizeof(struct mystruct) + 6 * sizeof(int));
for(int i=0;i<6;i++) {
var->array[i]=0;
}
You cannot change an already declared struct, but you can make a new one as you want by modifying the program. You can't change data structures used in the program on the fly while it is running.

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