c define arrays in struct with different sizes - c

I need to define a struct for two types of objects. Both have exactly the same data structure and perform same tasks (member methods).
The ONLY difference is that the array sizes are different in the two types, one using SIZE_A, the other SIZE_B.
Duplicating the definition of the struct and functions is not wanted.
How could I use one type of 'struct', and initialize its arrays with different sizes?
#define SIZE_A 100
#define SIZE_B 200
typedef struct{
int matr[SIZE_A][SIZE_A]; // for another type matr[SIZE_B]
int arr[SIZE_A]; // for another type arr[SIZE_B]
int size; // will be initialized to SIZE_A or SIZE_B
int var1, var2;
}s;
void task1(s* si){
...
}
void task2(s* si){
...

Even with a union, the struct will be as big as the largest of the two arrays.
Do one of these:
Ignore the overhead of the biggest array size. (Use one array or a union)
Create a separate struct for each type.
Dynamically allocate the array with malloc.

I would make matr a flexible array at the end of your struct. Then, I would stick the arr array into the last row of matr.
typedef struct {
int size;
int var1, var2;
int matr[];
} s;
static inline int size_ok_s (int size) {
switch (size) {
case SIZE_A:
case SIZE_B:
return 1;
default:
break;
}
return 0;
}
s * create_s (int size) {
s *x = 0;
if (size_ok_s(size)) {
x = malloc(sizeof(*x) + sizeof(int[size+1]));
if (x) x->size = size;
}
return x;
}
To achieve a uniform interface, you can use a macro:
#define s_matr(x) ((int (*)[(x)->size])(size_ok_s((x)->size) ? (x)->matr : 0))
#define s_arr(x) (s_matr(x)[(x)->size])
So, to access the ith row and jth column of s *foo's matr, and its kth element of arr:
s *foo = create_s(SIZE_A);
/* ... */
s_matr(foo)[i][j] = 0;
s_arr(foo)[k] = 0;
Flexible array members are a new feature of C.99 described in §6.7.2.1 ¶16. Prior to C.99, C programmers often used what was known as the struct hack:
typedef struct {
int size;
int var1, var2;
int matr[1];
} s;
s * create_s (int size) {
s *x = 0;
if (size_ok_s(size)) {
x = malloc(sizeof(*x) + sizeof(int[size]));
if (x) x->size = size;
}
return x;
}
This is a hack since in C.89-90, indexing the matr array with a value greater than 0 is technically accessing an object beyond its boundary. However, it was a common practice, and widely portable. C.99 formally sanctioned the mechanism with the flexible array member, although it requires the syntax of not specifying a size in the array declaration.

Have the arrays be pointers and allocate to them (the appropriate size) as needed. Only downsize is access to the 2D array will be a little clumsy.

Related

User defined types with dynamic size in C

I want to define a new data type consisting of an array with a size inputted by the user. For example if the user inputs 128, then my program should make a new type which is basically an array of 16 bytes. This structure's definition needs to be global since I am going to use that type thereafter in my program. It is necessary to have a dynamic size for this structure because I will have a HUGE database populated by that type of variables in the end.
The code I have right now is:
struct user_defined_integer;
.
.
.
void def_type(int num_bits)
{
extern struct user_defined_integer
{
int val[num_bits/sizeof(int)];
};
return;
}
(which is not working)
The closest thing to my question, I have found, is in here:
I need to make a global array in C with a size inputted by the user
(Which is not helpful)
Is there a way to do this, so that my structure is recognized in the whole file?
When doing:
extern struct user_defined_integer
{
int val[num_bits/sizeof(int)];
};
You should get the warning:
warning: useless storage class specifier in empty declaration
because you have an empty declaration. extern does not apply to user_defined_integer, but rather the variable that comes after it. Secondly, this won't work anyway because a struct that contains a variable length array can't have any linkage.
error: object with variably modified type must have no linkage
Even so, variable length arrays allocate storage at the point of declaration. You should instead opt for dynamic memory.
#include <stdlib.h>
typedef struct
{
int num_bits;
int* val;
} user_defined_integer;
void set_val(user_defined_integer* udi, int num_bits)
{
udi->num_bits = num_bits;
udi->val = malloc(num_bits/sizeof(int));
}
What you need is a VLA member, as asked about here. Basically, you declare a struct with a size field and one element's worth of storage as last member, and over-allocate it.
Imported from that question :
typedef struct Bitmapset {
int nwords;
uint32 words[1];
} Bitmapset;
Bitmapset *allocate(int n) {
Bitmapset *p = malloc(offsetof(Bitmapset, words) + n * sizeof *p->words);
p->nwords = n;
return p;
}
I want to define a new data type consisting of an array with a size inputted by the user. For example if the user inputs 128, then my program should make a new type which is basically an array of 16 bytes.
This is not possible in C, because C types are a compile-time thing and don't exist at all at run-time.
However, with a C99 conforming compiler, you might use flexible array member. You'll need a struct containing some members and ending with an array without any given dimension, e.g.
struct my_flex_st {
unsigned size;
int arr[]; // of size elements
};
Here is a way to allocate it:
struct my_flex_st *make_flex(unsigned siz) {
struct my_flex_st* ptr
= malloc(sizeof(struct my_flex_st) + siz * sizeof(int));
if (!ptr) { perror("malloc my_flex_st"); exit(EXIT_FAILURE); };
ptr->size = siz;
memset (ptr->arr, 0, siz*sizeof(int));
return ptr;
}
Don't forget to free it once you don't use it anymore.
Of course, you'll need to use pointers in your code. If you really want to have a global variable, declare it as e.g.
extern struct my_flex_st* my_glob_ptr;
Try this method-
#include<stdio.h>
#include<stdlib.h>
#include<limits.h>
struct user_defined_integer
{
int *val;
}user_int;
void memory_allocate(int num_bit)
{
int result;
result = (num_bit+CHAR_BIT-1)/CHAR_BIT; // since 8 bit =1 byte
user_int.val=malloc(result*sizeof(int));
if(user_int.val == NULL){
printf("Failed to allocate memory\n");
return ;
}
else
printf("Allocated %d bytes for val\n",result);
}
int main()
{
int num_bit;
printf("Enter the number of bits\n");
scanf("%d",&num_bit);
memory_allocate(num_bit);
// do your stuff here
free(user_int.val); // free the memory at the end;
return 0;
}

union types and flexible array member

I have a question about the flexible-length arrays in C structures (http://gcc.gnu.org/onlinedocs/gcc/Zero-Length.html).
typedef struct {
size_t N;
int elems[];
} A_t;
Now the general approach is quite obvious,
A_t * a = malloc(sizeof(A_t) + sizeof(int) * N)
a->N = N;
....
Now this seems to be awkward when trying to incorporate stuff into other structs or stack-based allocation. So something like the following snipet is bound to fail for N!=0
struct {
A_t a;
A_t b; /// !!!!!
double c; /// !!!!!
};
Now I think it should be possible to allow for usages like this by defining another type
typedef struct {
size_t N;
int elems[5];
} A_5_t;
struct {
A_5_t a;
A_5_t b;
double c; // should work here now.
} mystruct;
and then use it as if it were an A_t structure. When calling a function void foo(A_t * arg1);, one would need to use something like foo((A_t*) (&mystruct.b)). Which -- to me -- appears to be a bit clumsy. I therefore wonder whether there is a better way to do this. I wonder whether one could employ a union type for this somehow?
I am asking this question, because the flexible-length array makes it possible to have data in one piece in the structure, therefore one can copy a struct with a single command instead of having to worry about deep and shallow copies, etc.
You have a mult-layered question.
In this one example:
struct {
A_t b;
double c; /// fails
};
I would try:
struct {
double c;
A_t b;
};
Always place the variable portion of a struct at the end. Note, I don't use GCC, so try this, it might/maybe work.
To follow-up on a requirement given by #wirrbel, the following struct is NOT variable length, but it does define and provide access to a variable length array of integers.
typedef struct {
size_t N;
int *(elems[]); // parens to ensure a pointer to an array
} A_t;
A_t *a = malloc //etc.
a->elems = malloc(sizeof(int) * N);
In this fashion several A_t structures can be included in a more general structure.
No, in general your two struct, A_t and A_5_t, are not interchangeable. The reason is that the version with the flexible array can have different padding in front of the elems field than versions with a fixed field length.
Whether or not your compiler implements a different padding or not, you can test by using the offsetof macro. But even if the offsets are the same for your particular compiler and platform, you'd better not rely on that if you want portable code.
I have figured it out now (the solution has actually been descibed in the gnu documentation as provided above). By appending an array declaration after the struct declaration, one does create a contiguous memory range that is directly adjacent to the "empty" flexible array. Therefore b.A.elems[i] is referencing the same data as b.elems_[i].
It is probably advisable to choose an identifier that tells you that the memory of this array is actually belonging to the structure. at least thats how I would use it then.
typedef struct {
size_t N;
double elems[];
} A_t;
typedef struct {
A_t a;
double elems_[4];
} B_t;
void foo(A_t * arg1) {
for (size_t i=0; i < arg1->N; ++i) {
printf("%f\n", arg1->elems[i]);
}
}
int main(int argc, char *argv[]) {
B_t b;
b.a.N = 4;
for (int i=0; i < 4; ++i) {
b.elems_[i] = 12.4;
}
foo(&b.a);
}

Variable-length array in file scope?

I have this code for example.
#include <stdlib.h>
#include <stdio.h>
#define array_size 3
typedef struct {
int array[array_size];
} TEST;
void printout(TEST *p, int element) {
printf("element: %i\n", p->array[element]);
}
int main(void) {
TEST *p;
p = malloc(sizeof(TEST));
p->array[0] = 5;
printout(p, 0);
return 0;
}
But I'd like to assign "array_size" based on user input.
If I try to do so, the compiler says "variably modified ‘array_size’ at file scope". So, am I right that the only way to do what I want is to move everything to main()..?
It works just fine, but keeping structs and functions declarations in file scope seems, you know, neat.
The simplest approach is to just allocate the memory dynamically:
typedef struct {
int *array;
size_t size;
} TEST;
int main() {
size_t elem_count = /* from user input */
TEST p;
p->array = malloc(elem_count * sizeof int);
if(!p->array)
return -1;
p->size = elem_count;
/* ... */
free(p->array);
}
You can indeed not define a variable length array at file scope, you can however define a pointer at file scope and malloc it, just define a global pointer int* p = NULL; (lose the whole TEST stuff) and p = malloc(sizeof(int) * input_size); simply access with p[x].
For completeness, you can also use the so called flexible array member defined in C99:
From ISO/IEC 9899:1999, Section 6.7.2.1, paragraph 16:
As a special case, the last element of a structure with more than one
named member may have an incomplete array type; this is called a
flexible array member.
typedef struct {
other_type other_data
int array[];
} TEST;
...
TEST *p = malloc(sizeof(TEST) + sizeof(int) * input_size);
Though note that this is limited to a single member, you could make an array of structs if you would otherwise have multiple arrays of different types but the same length.
This was originally intended mostly for data with headers such as ofter encountered in file and/or network I/O.

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

With mmap() how can dynamically sized structures be created

Hi I have the following scenario
#define CONSTANT 10
struct structA{
int var1;
int var2[CONSTANT];
};
main(){
structA *varA = NULL;
int i;
/* some C code */
varA = mmap(0,..);
for(i = 0; i < CONSTANT; i++){
varA.var2[i] = /* C code */ ;
}
/* C code */
}
Here the number of elements in var2 array of structA is constant and hence the varA.var2[i] can be directly referenced . But If the number CONSTANT is to be determined dynamically during runtime , how should the structure definition be modified?
The cleanest way would be to use a C99 flexible array member:
struct structA{
int var1;
int var2[];
};
Then you can just mmap(NULL, sizeof(int) * (num + 1), ...). Just be careful with flexible array members, sizeof behaves funny with them (doesn't include their size).
If you can't / won't use a flexible array member, you can use a pointer instead of an array and mmap memory separately for it.
The most common way to do this is:
struct structA{
int var1;
int var2[1];
};
It's not really an array with a single element, because you allocate more memory than the size of a structA.
The number CONSTANT cannot be determined dynamically at runtime, since it affects the structure size.
The usual trick for what you're trying to do (I'm not sure if it's strictly valid C but it's very common) is to create
struct structA{
int var1;
int var2[0];
};
and when you map or allocate, allocate (sizeof(structA) + sizeof(int) * CONSTANT) bytes.

Resources