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.
Related
I'd like to write a library in C and I don't know what is the recommended way. I got for example structure and multiple functions like this:
typedef struct example
{
int *val;
struct example *next;
} Example;
and I have build function for multiple types of val
Example* build() { do sth };
Example* buildf() { do sth }; // val is float
Example* buildd() { do sth }; // val is double
What is the better practice (used in "professional" library). Use pointer to void and casting or have structure for all possibilities - int, float, double.
Use a union and some way to store type info:
typedef struct example
{
enum{ T_STRUCT_WITH_INT, T_STRUCT_WITH_FLOAT, T_SO_ON } type;
union {
int val_int;
float val_float;
} val;
struct example *next;
} Example;
Access fields after checking type by s->val.val_int
In C11 you can have union anonymous and fields can be accessed like s->val_int
This is primarily based on some combination of opinion, experience and the specific requirements at hand.
The following approach is possible, inspired by some container library work by Jacob Navia. I've never used it myself:
struct container_node {
struct container_node *link_here, *link_there, *link_elsewhere;
/*...*/
char data[0]; /* C90 style of "flexible array member" */
};
struct container_node *container_node_alloc(size_t data_size);
The allocation function allocates the node large enough so that data[0] through data[data_size-1] bytes of storage are available. Through another set of API functions, user data of arbitrary type be copied in and out.
The following approach is sometimes called "intrusive container". The container defines only a "base class" consisting of the link structure. The user must embed this structure into their own structure:
struct container_node {
struct container_node *next, *prev;
};
void container_insert(struct container *container, struct container_node *n);
struct container_node *container_first(struct container *container);
The user does this:
struct my_widget {
struct container_node container_links;
int widget_height;
/* ... */
};
/* .... */
/* We don't insert my_widget, but rather its links base. */
container_insert(&widg_container, &widget->container_links);
Some macros are used to convert between a pointer to the widget and a pointer to the container links. See the container_of macro used widely in the Linux kernel:
struct my_widget *wptr = container_of(container_first(&widg_container),
struct my_widget, container_links);
See this question.
Then there approaches of storing a union in each node, which provides an integer, floating-point-value or a pointer. In that case, the data is separately allocated (though not necessarily: if the caller controls the allocation of the nodes, it's still possible to put the node structure and the user data in a buffer that came from a single malloc call).
Finally, there are also approaches which wrap these techniques with preprocessor templating, an example of which are the BSD QUEUE macros.
I have three objects, which (at the moment) I am representing as structs:
a Dataset
a DatasetWindow
a MovingWindow
and a variable windowSize
There may be multiple Dataset's and each should have it's own DatasetWindow.
Ok, fair enough, to me that sounds like I make a DatasetWindow struct and put it as a member of a Dataset struct
There would be just one MovingWindow, but it should know about all the Dataset's.
Ok, so far it seems pretty simple. I create another struct for MovingWindow and it has a pointer to Dataset. (an array of datasets).
So so far, I have something like this:
typedef struct {
int *buffer;
int someOtherMember;
} DatasetWindow;
typedef struct {
int someMember;
DatasetWindow *window; //Pointer to a DatasetWindow obj.
} Dataset;
typedef struct {
int offset;
int someMember;
Dataset *datasets; //Array of Dataset
} MovingWindow;
The part I am having trouble with is this:
MovingWindow should know windowSize, as should each DatasetWindow.
But Dataset should preferably not need to know what windowSize is.
I don't know how to arrange my structures to support this?
You can modify the definitions of structs MovingWindow and DatasetWindow to incorporate a member (pointer or a interger variable) holding the value of your windowSize.
I have an abstract data type in C, LIST OF THINGS, ist node has a void* pointer, what i'm trying to do is create a function to compare an specific field of different structures in order to sort my list of things.
typedef struct node{
char *name;
void *thing;
struct node *next;
}Node;
This is the node i'm working with, i've already created a list of integers, list of structures and te compare function for both, but i can't figure out how to do a compare function to diferent structures. for example:
given these types:
typedef struct main{
float weight;
char*model;
float maxspeed;
}Main;
typedef struct airplane{
float weight;
float maxspeed;
}Airplane;
typedef struct car{
char*model;
float maxspeed;
}Car;
And this is the function, so you have an idea of what i'm trying to do, it doesn't work, Main has fields that doesn't exist in either one or the other structure.
int comparefunction(void*a,void*b){
Main a1, a2;
a1=*(Main*)a;
a2=*(Main*)b;
return a1.weight-a2.weight;
}
This function(doesn't work) is passed as a paremeter to the function that links the nodes in order to use the comparefunction.
//insert prototype:
//insert(Node*listp,Node*newp,int(*func_comp)(void*,void*));
list=insert(list,newItem(&car1),comparefunction);
list=insert(list,newItem(&airplane1),comparefunction);
list=insert(list,newItem(&airplane2),comparefunction);
How can i do to compare a single field of two or more different structures? assuming that i know what each structure contains
If you're trying to compare somewhat similar things, you can look into unions.
struct attributes{
float weight;
// other common things?
};
struct thing {
enum { Car, Main, Airplane } type;
struct attributes attrs;
union {
struct Car car;
struct Main main;
struct Airplane airplane;
} other_thing;
};
You'd change your list to store the thing struct, which is a structure that encapsulates all your possible types. The common elements of each type are extracted to the attributes struct. Your compare function would then operate on the attributes struct of the thing struct. The union is used here to only create enough space within struct thing for the largest of the union elements, so that you're not wasting space storing all three structs and only using one.
Well, your car struct doesn't have a weight field, so I'm not exactly sure what you're trying to accomplish here. If you had your car struct look like
typedef struct car {
float weight;
char* model;
float maxspeed;
} Car;
I think your function would work. Note, it is important that the member that you want to compare is at the same offset into each struct including the Main struct.
EDIT
This does work.
Another edit based on comments
You can't compare two completely unrelated things. This is not a technical deficiency with C. It just does not logically make any sense to compare for example an Airplane and an int.
I have a C structure that looks like this
typedef struct event_queue{
Event* event;
int size;
int front;
int count;
int delay;
} event_queue;
It's a basic circular queue. The event value is an array of EventPointers, and it's traversed every X time to dequeue one of the events.
It's initialized like
p->event = calloc(p->size, sizeof(Event));
Thing is, I want to do a similar queue, with similar functionality, to queue other type of similar events but with slightly different data. Initially I just wanted to have separate queues and traverse them separately, but the functionality is so repeated, it seems like I am just doing it wrong.
Imagine the "sister" queue as being exactly the same, but with a pointer to a different type for "event".
Should I use an union for this instead? such as
typedef struct event_queue{
union{
Event* event;
VisualEvent* visual;
} data;
unsigned char* datatype; //array of same size as data for every individual member
int size;
int front;
int count;
int delay;
} event_queue;
But in that case, how do I allocate memory for the array? Should I keep them separate, and this is a bad idea?
One solution is to make the basic event type a union, perhaps a tagged one:
enum EEventType { TypeOne, TypeTwo };
typedef struct EventTag_
{
EEventType tag;
} EventTag;
typedef struct EventOne_
{
EEventType tag;
// real data for this event type;
} EventOne;
typedef struct EventTwo_
{
EEventType tag;
// real data for the sister event type;
} EventTwo;
typedef union Event_
{
EventTag kind;
EventOne event1;
EventTwo event2;
} Event;
Now make an array of Events. For every Event * p, you can inspect e->kind.tag no matter which union member is active at that moment (thanks to a special rule concerning initial sequences of struct union members).
I am doing feature enhancement on a piece of code, and here is what i saw in existing code. If there is a enum or struct declared, later there is always a typedef:
enum _Mode {
MODE1 = 0,
MODE2,
MODE3
};
typedef enum _Mode Mode;
Similary for structure:
struct _Slot {
void * mem1;
int mem2;
};
typedef struct _Slot Slot;
Can't the structures be directly declared as in enum? Why there is a typedef for something as minor as underscore? Is this a coding convention?
Kindly give good answers, because i need to add some code, and if this is a rule, i need to follow it.
Please help.
P.S: As an additional info, the source code is written in C, and Linux is the platform.
In C, to declare a varaible with a struct type you would have to use the following:
struct _Slot a;
The typedef allows you to make this look somewhat neater by essentially creating an alias. And allowing variable declaration like so:
Slot a;
In C there are separate "namespaces" for struct and typedef. Thus, without a typedef you would have to access Slot as struct _Slot, which is more typing. Compare:
struct Slot { ... };
struct Slot s;
struct Slot create_s() { ... }
void use_s(struct Slot s) { ... }
vs
typedef struct _Slot { ... } Slot;
Slot s;
Slot create_s() { ... }
void use_s(Slot s) { ... }
Also see http://en.wikipedia.org/wiki/Struct_(C_programming_language)#typedef for details, like possible namespace clash.
If the following is a structure:
struct _Slot {
void * mem1;
int mem2;
};
you need the following to declare a variable:
struct _Slot s;
Notice the extra struct before _Slot. It seems more natural to declare a variable like Slot s, isn't it?
If you want to get rid of extra struct, you need a typedef:
typedef struct _Slot Slot;
Slot s;
It's sort of code obfuscation technique which only make sense in small amount of cases.
People say it's more natural to not write "struct" and other subjective things.
But objectively, one at least a) can't forward declare such typedeffed struct, b) have to jump through one hoop when using ctags.