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
Related
After juggling and trying to learn how to get this done I thought it's time to ask the experts.
I have more than one structures and would like to "manipulate" the data in them using only one node.
What is the best way to do this?
code example:
typedef struct printQuality{ int dpi; } quality ;
typedef struct paperSize{ char* dim; } sizes ; //this would be A3 , A4 this is why i picked char
typedef struct printColour{ char* color; } colors;
typedef struct printStyle{ char* side; } sides;
typedef struct printOrientation { char* orientation; } orientations;
typedef union printOptions{
quality dpi;
sizes size;
colors color;
sides side;
orientations orientation;
} options;
struct optNode{
options* inf;
optNode* next;
optNode* prev;
};
From your comments, I believe your issue has to do with the behavior of Unions in C vs structs. In C/C++, Unions are structures which can only instantiate one of their values at a given time. With your printOptions union, you have 5 variables. At any given time, only one of those variables (the last one you set) is guaranteed to hold a value. Here is a good article on how Unions work: https://www.programiz.com/c-programming/c-unions. Structs in C/C++ do not have this behavior. Whichever values you set remain set until the instance of the struct goes out of scope or is deleted. I think that if you make printOptions a struct, you will be able to access all of your other structs from your options pointer in your optNodes.
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.
I've seen some C code that creates a structure and within the structure there are a number of arrays. Some of those arrays are of size one. So why bother making it an array? Why not just a single int?
I'm talking about something like this:
struct Foo
{
uint8_t Bar[1];
uint32_t BigBar[4];
};
Why not make it just
struct Foo
{
uint8_t Bar;
uint32_t BigBar[4];
};
The answer is that it is good programming habit to do so from two reasons:
In case the programmer decides to change the Bar into an array at some point, there is not a lot of code changing. All needed to be done is to change the constant from 1 to ARRAY_SIZE (it is even better to have the constant defined as one actually)
Using fields which are constructed the same are less prone to mistakes than fields which are different. Thinking programmers are ones who make mistakes :)
Cheers
My guess is for an easier return of a pointer:
it will be easier to return the pointer to the variable:Bar
if you will want to use it as a pointer you would be able to pass Bar instead of &Bar if it was an int
if I had an instance of the struct defined:
struct Foo aaa;
you would be able to define:
int *pInt = aaaa.Bar;
instead of:
int *pInt = &(aaaa.Bar);
Consistency with other structs?
struct alien {
int heads[3];
...
};
struct human {
int heads[1];
...
};
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.
I am implementing a PSO Algorithm. I use this
data structure:
typedef struct {
float x;
float y;
} C_struct_Class2D;
typedef struct {
C_struct_Class2D *pos;
C_struct_Class2D *best_pos;
C_struct_Class2D *vel;
} C_struct_Particle;
typedef struct { <br>
C_struct_Particle **particles;
C_struct_Particle *g;
} C_struct_Swarm;
I have to work with C, not with C++. That's why I use structs instread of classes.
Description of the strucs:
There is a Swarm(C_struct_Swarm) which consists of several Particles(**particles) an an optimum Particles(*g). Each Particle has a Position, Best Position and Velocity of Type
"C_struct_Class2D".
In a few methods I allocate memory space for each data and initialize it. But I' like
the whole data structure to be continuous in the memory. So that all structs are
behind each other in the address space.
The memory should look like:
C_struct_Swarm
particles[0]
particles[0]->pos
particles[0]->best_pos
particles[0]->vel
particles[1]
particles[1]->pos
particles[1]->best_pos
particles[1]->vel
...
...
...
...
particles[n]
particles[n]->pos
particles[n]->best_pos
particles[n]->vel
g->pos
g->best_pos
g->vel
How can I achieve this?
Regards
sw
Compose members by value
Include C_struct_Class2D by value inside C_struct_Particle:
typedef struct {
C_struct_Class2D pos;
C_struct_Class2D best_pos;
C_struct_Class2D vel;
} C_struct_Particle;
This guarantees the order of those members (pos is before best_pos is before vel).
Allocate an array of items, instead of an array of pointers to items
typedef struct {
C_struct_Particle *particles;
int num_particles;
C_struct_Particle g;
} C_struct_Swarm;
I should note that here, the data pointed to by particles is NOT contiguous with the other members, so what you are asking for is not entirely possible, unless you do something else like set g to always be the first particle, i.e. included in the particles "array".
Watch out for padding
If you don't care about padding (and in your code example it looks like you don't), then skip this. Otherwise it's platform/compiler specific. In GCC for example, you can use the packed attribute:
struct __attribute__ ((__packed__)) my_packed_struct
{
char c;
int i;
};
You cannot in the way you have described. If you want continuous blocks of memory, the only solution (as far as I know) is to use buffers (see my similar answer that might give you an idea how to implement it).
If you use gcc, for static object you could try __attribute__... more info here http://gcc.gnu.org/onlinedocs/gcc-3.1/gcc/Variable-Attributes.html
iw source code as example