I'm writing in C and would like to have some implementation of type variables. In Haskell for example I could write something like:
data Matrix a = Matrix [a] Int Int
which would let me define matrices with entries of any type 'a'. In C, I've written for each type some structure:
struct zMatrix {
int dim_row;
int dim_col;
int *coords;
};
struct rMatrix {
int dim_row;
int dim_col;
float *coords;
};
...
Is there some way to have a generic matrix structure and some function to create a matrix which would specify the type of the coords field? Something like:
struct matrix {
int dim_row;
int dim_col;
(typevar type) *coords;
};
struct matrix matrixCreate(typevar type, int n, int m){...};
struct matrix M = matrixCreate(int, 3, 3);
struct matric M = matrixCreate(float, 3, 3);
...
You can do it. As #EOF mentioned, you can use a union type for the portion of the structure that is different for different data types. You'll probably want to store something representing the type in the structure as well. You can't pass a type name to a function as in your example, but you can define an enum that represents the various types. You would then use switch statements to implement any type-specific code. An alternative to using switch statements is to use a data structure which describes a type (this would contain function pointers and possibly other information). You would declare an instance of that data structure for each type and your type-specific code would use information in the appropriate type's data structure to do what it needs to do. The type data structures could be in an array which you would index with the type enum value, or you could use a pointer to the type data structure to represent the type.
If C++ is an option, that would make this a lot easier.
Related
I'm practicing C and it seems very tedious having to write algorithms for essentially the same data structures but that hold different data, especially since no namespace means I have to give extralong titles to everything
for example:
//double matrix
typedef struct DubMatrix DubMatrix;
struct DubMatrix {
int rows;
int cols;
double *data;
};
// int matrix
typedef struct IntMatrix IntMatrix;
struct IntMatrix {
int rows;
int cols;
int *data;
};
I have many functions that I would like to implement dealing with (among other things) matrices of different types of numbers, like algebraic numbers, elements of finite fields, etc.
I'm wondering if there is a way to avoid redoing essentially the same structs and functions over and over.
You could use tagged unions which are basically structures containing common data, and most importantly a tag field denoting the type, and a union for the data itself.
It could look like
struct Matrix
{
size_t rows;
size_t cols;
enum
{
INT,
DOUBLE
} type;
union
{
int *int_data;
double *double_data;
} data;
};
Then depending on the value of type you use either data.int_data or data.double_data.
Another possible solution is similar to the above, but instead of a union use a void * pointer for the data, and cast it as needed.
C does not really have the concept of generics or generic programming however there are a couple of tricks you can use.
You can use void pointers but they should be allocated big enough for the biggest thing you will store in them otherwise you will just access some place you are not supposed to.
Another thing you can use for generic-ish programming is unions which can have different variants consider following example which is one of standard oop polymorphism examples
struct triangle {...}
struct rectange {...}
union shape {struct triangle *;struct rectange *;}
enum type {triangle,rectangle}
struct shape {union shape *s,enum type type} /* this is like an interface*/
size_t area(struct shape *shape){...}
this looks tedious but could be easily generated through a macro
I have a code like this
typedef struct
{
unsigned char arr[15]; //size = 15bytes
unsigned char str_cks; //size = 1byte
}iamstruct; //Total Size = 16bytes
typedef union
{
iamstruct var;
unsigned char union_cks[16];
}iamunion; //Total Size = 16bytes
static iamunion var[2];
int main()
{
printf("The size of struct is %d\n",sizeof(iamstruct)); //Output = 16
printf("The size of union is %d\n",sizeof(iamunion)); //Output = 16
var[1].union_cks[1] = 2;
printf("%d",var[1].union_cks[1] ); // Output =2
return 0;
}
I'm confused with struct variable declaration inside the union and how it works?.
What is the main purpose of doing this & How it improves accessibility?
Please share your ideas.
Thanks in advance.
I understood something now from the below code. Here memory allocated is 16bytes and its all shared by an individual member of union.
typedef struct
{
unsigned char str_cks1;
unsigned char str_cks2;
unsigned char str_cks3;
unsigned char str_cks4;
unsigned char str_cks5;
unsigned char str_cks6;
unsigned char str_cks7;
}iamstruct;
typedef union
{
iamstruct var;
unsigned char union_cks[7];
}iamunion;
static iamunion var[7];
int main()
{
int i = 0;
printf("The size of struct is %d\n",sizeof(iamstruct));
for(i=0;i<7;i++)
{
var[i].var.str_cks1 = (i*1);
var[i].var.str_cks2 = (i*2);
var[i].var.str_cks3 = (i*3);
var[i].var.str_cks4 = (i*4);
var[i].var.str_cks5 = (i*5);
var[i].var.str_cks6 = (i*6);
var[i].var.str_cks7 = (i*7);
}
for(i=0;i<7;i++)
{
printf("%d\t",var[i].var.str_cks1);
printf("%d\t",var[i].var.str_cks2);
printf("%d\t",var[i].var.str_cks3);
printf("%d\t",var[i].var.str_cks4);
printf("%d\t",var[i].var.str_cks5);
printf("%d\t",var[i].var.str_cks6);
printf("%d\t",var[i].var.str_cks7);
printf("\n");
}
return 0;
}
Output:
enter image description here
A struct represents the values corresponding to the cartesian product o the types of all its fields. These values are the ordered concatenation of the field values and all are present in every single struct value. In this sense, you'll see all the values in the fields as a tuple, or sequence, of values, each of the type of the field they represent.
On the contrary, a union represents an alternative of every field inside, so the whole set of values of the type is the plain union of each of the types inside it.
So, composition (of union and struct) ensures that you can set an ordered sequence of values(struct) or see the struct field as a single alternative to the union. Easy, right! :) (you can also have a union as a field of a struct, meaning this time that the field in the sequence is an alternative of possible sets of values.
Let's see it with an example. Let's assume you have a variable which is supposed to store Real or Complex values. For Real you just use a plain float value (I will over complex this on purpose, to see how it expands) and for Complex we'll use it two double values (this selection has nothing to do with the other alternative and the lose of precision of a float against a double) You can use:
struct complex {
double real_part, imaginary_part;
};
and then
union {
float real_number;
struct complex complex_number;
} my_variable;
then you can access my_variable.real_number as the single precision float value, and my_variable.complex_number.real_part and my_variable.complex_number.imaginary_part as the double precision double real part and imaginary part of a complex number.
Beware that this is not a way to convert values from real to complex or viceversa. Indeed, in this example, both types of values have different representation internally, and you'll mangle your data if you store a single precision float real number on the variable and try to access it as a complex number (you'll have to externally manage the kind of value you have stored in the variable in order to know how to access it) The set of values storable in the variable will be the whole set of float values for real numbers, plus(or also) the whole set of double pairs or real parts and imaginary parts that conform the complex numbers. This is where the union reserved word was taken from.
It is important to consider that a type represents the set of values storable in a variable of that type. In this way, a struct allows you to store a value of each of the types that the fields represent, and you can store all of them at the same time on the variable, while a union only allows you to decide which type (and which field) you'll use to store only a single value of any of those field alternatives, and no more than one.
In the C programming language described in the second edition of K&R's book, a struct or union is a sequence of bytes, and a struct or union member is a means of interpreting some of the storage within the struct or union as that type. Within a struct, all members are assigned to disjoint regions of storage, while all union members use the same storage.
If the members of the structures are stored consecutively, then given:
struct s1 {char a[3],b[5]; };
struct s2 {char a[5],b[3]; };
union { struct s1 v1; struct s2 v2; } u;
the storage assigned to u.v1.b[3] would also be assigned to u.v2.b[1], so a write to either would effectively set the value in both.
The C Standard allows for other dialects of C which would impose additional restrictions on when objects may be read or written, either in cases where it would allow implementations to generate more efficient code or otherwise benefit their customers, or in cases where it would hurt an implementation's customers but the implementer doesn't care. There has never been any consensus about exactly what additional restrictions should be expected, and because the authors of the C Standard assume that implementers will seek to benefit their customers, there was never any real effort to formulate rules that would not rely upon such benevolence.
I am trying to implement a generic and dynamic set data structure, yet I am struggling with the generic part. I understand that it is essentially an array of type pointer-to-void, but I just do not know how to enable the user to choose the type of the elements to add to a particular set. I have searched this site thoroughly, yet there does not seem to be an answer to my question. The dynamic_set type is defined as follows:
typedef struct
{
int size;
int capacity;
void ** data;
} dynamic_set;
I need to know the type of the elements in order to be able to typecast the pointers and eventually dereference them so that I can check if the sets are compatible for a union, to decide on what type of function to apply to return an aggregate value, etc. Should I include another member in the above structure which represents the type of the elements within that set, like an enum? Any help is vastly appreciated!
I can propose you to use pointers-to-functions to provide operations over the pointer stored values:
struct DynamicSet
{
void** Items;
size_t Size;
size_t Capacity;
int (*compare)(void*, void*);
};
DynamicSet* DynamicSet_Create(size_t capacity,
int (*compare)(void*, void*));
int CompareInts(void* left, void* right)
{
int leftInt = *((int*)left);
...
}
DynamicSet* dynamicSet = DynamicSet_Create(100, CompareInts);
To use it with other type you just write another Comparator function.
But if you want more type safety and more convenient signatures for you functions you may try to emulate C++ templates with macro substitution.
This is in C. I have a handle which I use throughout many files (let's call it type_handle), which is an enum presently, but currently I would need to extend it to support a typedef-ed struct (called my_type) as well. Since many functions take type_handle as an input parameter, I don't want to change the design majorly so that I need to redo all the files. So my idea is to pass int, float, double and then my_type. I want to have some sort of a union function of all types I want, so that I don't need to modify functions taking type_handle. How should I design this?
typedef enum
{
INT = MPI_INT,
INT8 = MPI_INT8_T,
INT16 = MPI_INT16_T
}
types_t;
typedef union {
my_type dtype;
types_t etype;
} type_handle;
I want to design this in a way such that any_func(type_handle type) could accept any_func(INT) as well as any_func(dtype) where dtype is say a derived datatype of type my_type.
When using a union in C you need some way to know which member to use. C itself cannot tell you which element of your union is the one you assigned. This will be confusing to explain, since you are already dealing with types, but the idiom would be:
struct {
what_is_in_the_union_t what;
union {
type_a a;
type_b b;
...
} u;
};
Where what_is_in_the_union_t is your own enum of { TYPE_A, TYPE_B, ... }. As I said, this will expand in a confusing way in your example because your inner type_a is already a types_t.
I'm looking to implement a dictionary data structure in C which I want to be as generic as possible. That is to say it can accept a pair of values that can be of any type.
How can I init a variable that can accept any types?
And how can I convert that type back to a type I want? (Typecast)
Thanks.
The way to define a variable that can hold values of more than one type is to use unions:
union uu {
int i;
float f;
char c;
char *s;
} x;
x.i is an integer, x.s a char pointer etc. and the size of x is the maximum among the sizes of the members type.
Unfortunately the only way to remember the type of the variable is to store it somewhere else. A common solution is to have a structure like this:
struct ss {
int type;
union {
int i;
float f;
char c;
char *s;
} val;
} x;
And do something like:
#define FLOAT 1
#define INT 2
....
x.val.i = 12;
x.type = INT;
....
if (x.type = INT) printf("%d\n",x.val.i);
....
really ugly.
There are other possibility playing with the macro processor to make it a little bit more pleasent to the eye but the essence is that you have to know in advance the type of the value stored in the union and access the proper field.
This isn't trivial to do, but here's the simplest way to do it:
You need to know all the types you'll support, and what they are when you insert them.
First, you'll actually have a data structure of some struct like
struct { void * data; enum Type tag }
and define an enum Type { int, char*, ... etc }
The void * is a pointer to data without a type, so you can use it to store to a chunk of memory that contains the data you want to store.
The Type tag stores what the data is so that your code using it can know what is being returned from your data structure.
If you don't need to store the type, and you can cast it back to the correct type when you pull it out of your data structure, then you can omit the Type tag and just store void *
In C there is no easy way to do this. You can use void* and pass around pointers to the types, but there is no concept of templates or generics or variants that exists.
To use void* you would need to treat everything as a pointer so would have to allocate it on the heap. You would then need to cast those pointers to void* when sending to this data structure and then cast back on the other side. This can be tricky because you have to remember what the types were to start with.
If you happen to be programming on Windows you can use Variants to do this, but there is some overhead associated with it.
You probably want void *.
You've got two options:
void* foo;
which can point to data of any type, or:
union my_types {
int* i;
char* s;
double* d;
bool* b;
void* other;
}
which gives you "automatic" pointer casting (in that you can reference a variable of type "my_types" as if it were any of the above types). See this link for more on unions.
Neither is a great option -- consider C++ for what you're trying to do.
Use a void * ?
You can typecast to whatever you want provided of course you must perform the checking yourself.
Your solution will have to use pointers to void.
Pointers to void can hold the address of any object type (not functions) and can be converted back without loss of information.
Best is to use a "parent structure" so that you know the type of the object pointer to:
enum MyType { INTEGER, DOUBLE_STAR };
struct anytype {
enum MyType mytype;
size_t mysize;
void *myaddress;
};
and then
struct anytype any_1, any_2;
int num_chars;
double array[100];
any_1.mytype = INTEGER;
any_1.myaddress = &num_chars;
any_1.mysize = sizeof num_chars;
any_2.mytype = DOUBLE_STAR;
any_2.myaddress = array;
any_2.size = sizeof array;
and, to work with that
foo(any_1);
foo(any_2);
where foo is defined as
void foo(struct anytype thing) {
if (thing.mytype == INTEGER) {
int *x = thing.myaddress;
printf("the integer is %d\n", *x);
}
if (thing.mytype == DOUBLE_STAR) {
size_t k;
double *x = thing.myaddress;
double sum = 0;
for (k = 0; k < thing.mysize; k++) {
sum += thing.myaddress[k];
}
printf("sum of array: %f\n", sum);
}
}
CODE NOT TESTED
You can use a void * pointer to accept a pointer to pretty much anything. Casting back to the type you want is the tricky part: you have to store the type information about the pointer somewhere.
One thing you could do is use a struct to store both the void * pointer and the type information, and add that to your data structure. The major problem there is the type information itself; C doesn't include any sort of type reflection, so you'll probably have to create an enumeration of types or store a string describing the type. You would then have to force the user of the struct to cast back from the void * to the original type by querying the type information.
Not an ideal situation. A much better solution would probably be to just move to C++ or even C# or Java.
enum _myType { CHAR, INT, FLOAT, ... }myType;
struct MyNewType
{
void * val;
myType type;
}
Then you could pass elements of type MyNewType to your functions. Check the type and perform the proper casting.
C offers unions which may suit your purposes, you need to define all the types before compilation but the same variable can point to all the types you include in the union.