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).
Related
I currently try to write some lil literal console game for fun in C.
For that, i need to be able to print window-like structures in ... well ... C.
I want to use a generic rendering method (lets call it frame_render(...)) to render all different "ui elements"
The problem now is: how to solve this?
given the scenario:
// Theoretical base
struct frame { int x; int y; int width; int height; }
struct button { int x; int y; int width; int height; ... }
struct whatever { int x; int y; int width; int height; ... }
how could i ensure that my x, y, width and height are always in the correct spot memory wise?
is it enough to "just" put them in the same order at the very begining?
also, how to design the method header to accept it?
If all of the structures start with members of the same types, in the same order, corresponding members will have the same offsets. Most compilers can be configured to allow a pointer of any structure type to be used to inspect members of the Common Initial Sequence of any other, but there are a few issues:
On some unusual platforms, if an object is followed by padding bytes, an instruction that writes the object and padding bytes together (likely storing meaningless values in the latter) may be faster than instructions that write only the object. If a member is followed by a padding byte in some structures, but by meaningful data in another, a write to that member using the type where it's followed by padding bytes may write overwrite the "padding bytes" with meaningless values, thus corrupting the values of the following members in the other structure types. I am unaware of any architectures in current use where this would be an issue for any struct members other than bitfields, and I am unaware of any current implementations where this would be an issue even for those, but such possibilities could arise on some platforms, especially with bitfields.
Given something like:
int readField1OfS1(struct s1 *p) { return p->field1; }
struct s2 *myStruct2Ptr;
if (readField1ofS1((struct s1*)myStruct2Ptr)
...
some compilers like gcc and clang won't reliably allow for the possibility that the value returned from the function might depend upon a value held by part of the Common Initial Sequence of an object of type struct s2 at the time of the call unless optimizations are disabled (e.g. using the -fno-strict-aliasing option). I would think that presence of a cast from struct s2* to struct s1* within the function call expression should allow a quality compiler to recognize that anything function might do something with an object of type struct s1 might be done on a struct s2, but since the Standard doesn't explicitly require that, the authors of gcc and clang refuse to make any effort to reliably recognize such constructs even in straightforward cases like the above.
Code which makes use of the Common Initial Sequence rule will work reliably on nearly any suitably-configured compiler, but some like gcc and clang must be specially configured using -fno-strict-aliasing option. The ability to exploit Common Initial Sequence guarantees has been a well-established part of the language since 1974, and when the Standard was written, anyone familiar with the language would have understood that it was designed to allow for constructs like those above, which compilers should have no difficulty recognizing. Since the authors of the Standard failed to explicitly require that the CIS guarantees be honored in useful fashion, however, the authors of clang and gcc have decided they'd rather claim that programs relying upon the decades-old CIS guarantees is "broken" than honor 40+ years of precedent.
is it enough to "just" put them in the same order at the very begining?
Yes, if you're careful as you've done above.
also, how to design the method header to accept it?
There are different ways to do this.
Here's an example, using the [ugly] equivalent of a c++ "base" class:
enum type {
FRAME,
BUTTON,
WHATEVER
};
struct geo {
int x;
int y;
int width;
int height;
enum type type;
};
struct frame {
struct geo geo;
};
struct button {
struct geo geo;
int updown;
};
struct whatever {
struct geo geo;
int what;
int ever;
};
void
frame_render(struct geo *geo)
{
struct frame *frm;
struct button *but;
struct whatever *what;
switch (geo->type) {
case FRAME:
frm = (struct frame *) geo;
frame_render_frame(frm);
break;
case BUTTON:
but = (struct button *) geo;
printf("x=%d y=%d updown=%d\n",geo->x,geo->y,but->updown);
frame_render_button(but);
break;
case WHATEVER:
what = (struct whatever *) geo;
printf("x=%d y=%d what=%d ever=%d\n",
what->geo.x,what->geo.y,what->what,what->ever);
frame_render_whatever(what);
break;
}
}
Here's a way to use a virtual function table:
enum type {
FRAME,
BUTTON,
WHATEVER
};
struct geo;
// virtual function table
struct virtfnc {
void (*calc)(struct geo *);
void (*render)(struct geo *);
};
struct geo {
int x;
int y;
int width;
int height;
enum type type;
struct virtfnc *fnc;
};
struct frame {
struct geo geo;
};
struct button {
struct geo geo;
int updown;
};
struct whatever {
struct geo geo;
int what;
int ever;
};
void
frame_render(struct geo *geo)
{
struct frame *frm = (struct frame *) geo;
// whatever
}
void
button_render(struct geo *geo)
{
struct button *but = (struct button *) geo;
// whatever
}
void
whatever_render(struct geo *geo)
{
struct whatever *what = (struct whatever *) geo;
// whatever
}
void
any_render(struct geo *geo)
{
geo->fnc->render(geo);
}
Here's a third way that uses a union. It is simpler but requires that the base struct be as large as the largest sub-class:
enum type {
FRAME,
BUTTON,
WHATEVER
};
struct frame {
...
};
struct button {
int updown;
};
struct whatever {
int what;
int ever;
};
struct geo {
int x;
int y;
int width;
int height;
enum type type;
union {
struct frame frame;
struct button button;
struct whatever what;
} data;
};
void
any_render(struct geo *geo)
{
switch (geo->type) {
case FRAME:
render_frame(&geo->data.frame);
break;
case BUTTON:
render_button(&geo->data.button);
break;
case WHATEVER:
render_whatever(&geo->data.what);
break;
}
}
UPDATE:
is this approach casting safe? eg. putting all into some array that is of the type frame* and then just accessing frame->geo? or would that cause any problems with later calls to free(..)?
No problem with free if allocations are done with the derived types (e.g. frame, button), but not the base type geo: malloc(sizeof(struct button)).
To have a simple array [of shapes], the union method would need to be used (i.e. all derived structs must have the same size). But, this would be wasteful if we had some subtype that used a lot more space than the others:
struct polyline {
int num_points;
int x[100];
int y[100];
};
This could still be done with methods #1 or #2 [where the subtype structs are of different sizes] with an indirect pointer array:
void
all_render(struct geo **glist,int ngeo)
{
for (; ngeo > 0; --ngeo, ++glist)
any_render(*glist);
}
Rather than an array of different shapes, I'd consider a [doubly] linked list. This allows the subtype structs to have different sizes. We'd add a struct geo *next element to struct geo. Then, we could do:
void
all_render(struct geo *geo)
{
for (; geo != NULL; geo = geo->next)
any_render(geo);
}
The list approach may be preferable, particularly if we add/remove shapes on a dynamic basis [or reorder them based on Z-depth].
Or, some shapes might contain others. So, we could add struct geo *children to struct geo. Then, it's easy to (e.g.) draw a containing box, then all the shapes within that box by traversing the children list. If we go for children, we may as well add struct parent *parent as well so each shape knows what shape contains it.
The "classical" method is to have a struct that contains a union of all possible objects and an enum that identifies which exactly object has been passed:
struct renderable {
enum {FRAME, BUTTON, WHATVERE, ...} type;
union {
struct frame frame;
struct button button;
struct whatever whatever;
....
} data;
};
After passing this struct to the renderer, use a switch on the type field to extract the coordinates, etc:
void renderer (renderable *obj, ...) {
...
switch(obj->type) {
case FRAME: x = obj->data.frame.x; ...; break;
case BUTTON: x = obj->data.button.x; ...; break;
...
}
...
}
It was reportedly this kind of monstrosity that encouraged Stroustrup to invent C++ :)
Edited
Another "classical" solution is to have a separate struct that has the dimensions and the position of any object:
struct geometry {
int x, y, width, height;
}
You can store this structure at the beginning of any object-specific struct and use a cast to gain access to it:
struct frame {
struct geometry geo;
// more stuff
};
struct frame frame = {....};
rendered((void*)&frame, ...);
In the renderer:
void renderer (void *obj, ...) {
...
struct geometry *geo = (struct geometry *)obj;
geo->x ...
}
The latter approach may be somewhat unsafe. To make it 100% safe, separate the geometry from the object-specific information and pass them to the renderer as two separate structs.
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.
Say we have an instance of
struct Message {
char * topic;
int topicLength;
void * data;
int dataLength;
};
and we want to recreate it as an object of other type
struct CoreMessage {
int messaageId;
char * topic;
int topicLength;
void * data;
int dataLength;
char * senderId;
int senderIdLength;
};
Can we safly turn Message A into CoreMessage B? thing in C without copying contents, having types partly overlaping as shown here?
You can fake this with anonymous structures/unions. Anonymous structures have admittedly only been standardized since C11 but many popular compilers have supported them as an extension for ages.
That is something along these, admittedly-less-than-pretty, lines:
struct Message {
char * topic;
int topicLength;
void * data;
int dataLength;
char * senderId;
int senderIdLength;
};
struct CoreMessage {
int messageId;
union {
struct Message;
struct Message message;
};
};
No, you cannot do what you ask. You could come close, however, if you were willing to change the layout of struct CoreMessage like so:
struct CoreMessage {
struct Message message;
int messaageId;
char * senderId;
int senderIdLength;
};
Note that struct CoreMessage then contains an actual struct Message as a member (as opposed to a pointer to one). Then, given ...
struct CoreMessage cm;
struct CoreMessage *cmp = &cm;
struct Message *mp = &cm.message;
... you have (void *) cmp == (void *) mp, which can be useful for some of the kinds of things you might want to do. This is also adjusts automatically to changes to struct Message.
Alternatively, you can do something like this:
struct Message {
char * topic;
int topicLength;
void * data;
int dataLength;
maximum_alignment_requirement_t resv1;
char resv2[AS_MANY_BYTES_AS_ANY_MESSAGE_TYPE_MAY_NEED_INCLUDING_PADDING];
};
struct CoreMessage {
char * topic;
int topicLength;
void * data;
int dataLength;
maximum_alignment_requirement_t resv1;
int messaageId;
char * senderId;
int senderIdLength;
};
struct Message msg;
struct CoreMessage *cmp = (struct CoreMessage *) &msg;
That has a high probability of working as you would hope (and some system interfaces work pretty much this way) but C does not guarantee that those corresponding elements will be laid out the same way in the two different struct types.
Note, too, that it was no accident that I moved CoreMessage.messageId after the members corresponding to those of struct Message. It is much harder to arrange for corresponding layout if you do not do this, and the pointer value equivalence of the first alternative depends on it.
Not sure what you mean by "safely turn", but I would expect the answer to be "no". The structures are different, of course the smaller one can't magically be expected to expand into memory it didn't previously use.
There is no concept of "overlapping types" in C.
You can of course declare CoreMessage in terms of Message, but it won't help for the reverse transform from the smaller to the larger type except by making the transfer of the shared information easier:
struct CoreMessage {
int messageId;
struct Message message;
char *senderId;
int senderIdLength;
};
Now if we have:
struct Message a = { ... }; /* fully initialized */
struct CoreMessage b; /* we want to convert Message into this */
we can do:
b.messageId = 4711;
b.message = a; /* Copy all Message data over. */
b.senderId = "foo";
b.senderIdLength = 3;
Nothing is automatic here though, you have to do it yourself.
I'm not sure exactly what you mean by "turn into". I'm not sure how you can get casting to do this for you.
But, the C standard allows the compiler to put unused space between fields of a struct so, in general nothing would really work. You could make "CoreMessage" contain a "Message" and produce your result with a single assignment.
I have a struct defined like this:
struct GameState {
int score;
int moves;
bool won;
void *metadata;
};
typedef struct GameState GameState;
The metadata pointer will point to another struct of a type decided at runtime. For example it might be:
struct KlondikeMetadata{
bool draw3;
int drawcount;
};
typedef struct KlondikeMetadata KlondikeMetadata;
Or maybe:
struct FreeCellMetadata{
int reserveCells;
};
typedef struct FreeCellMetadata FreeCellMetadata;
The actual metadata struct used depends on the game the user is playing. 99% of the time this isn't a problem because I know what game the user is playing. However, there are cases where I don't (and can't) know this.
My question is, is there a way to determine or specify the correct metadata type at runtime?
For example if I could add a property to the GameState struct indicating that the metadata value is of type KlondikeMetadata and use that to cast the metadata to that type, I think I'd be golden. Is there a way to do this? Is there a way to specify a type and cast a variable at runtime in C?
You're going to have to encode it yourself.
The easiest solution is to declare an enumeration:
typedef enum {
GameType_Klondike,
GameType_FreeCell,
} GameType;
then add a field of that type before the pointer:
GameType game_type;
void *metadata;
Of course, this means you're going to have to set the game_type field when you initialize metadata, to remember the type.
You can also go a bit object-oriented, and have the GameType be part of the metadata:
struct Metadata {
GameType gametype;
};
struct FreeCellMetadata {
struct Metadata meta;
/* rest of fields here */
};
struct KlondikeMetadata {
struct Metadata meta;
/* rest of fields here */
};
Then you can cast your void * to struct Metadata *, and inspect the gametype field before casting the pointer to the proper type.
For bonus points, use a union:
struct Metadata {
GameType type;
union {
struct KlondikeMetadata klondike;
struct FreecellMetadata freecellL;
} game;
};
Again, of course this requires you to maintain the data, i.e. when you initialize a struct KlondikeMetadata you must remember to set its gametype field, and so on.
Inside of this first step towards a bootstrapped scheme interpreter I find the following set of typedef, struct, union, and enum definitions:
typedef enum {FIXNUM} object_type;
typedef struct object {
object_type type;
union {
struct {
long value;
} fixnum;
} data;
} object;
In particular, I'm not sure I understand the point of the struct inside the union (struct { long value; } fixnum;) -- a struct with only one field, to hold a single long? Very strange.
But I'm not really sure I understand the larger point, too. I think what's going on with the enum definition is that he's setting up a number of possible type values for lexical entities, and that object is a way of holding these, but perhaps somebody with more practice in C than I have can offer a more detailed explanation.
Thanks!
You're right, the struct-inside-a-union-inside-a-struct is rather useless in this code, but the author is using it as a stepping stone for the later code. Since he knows what the future code is going to look like, he can prepare the earlier code to make the changes as minimal as possible.
In the second part of the tutorial, the definition expands to this:
typedef enum {BOOLEAN, FIXNUM} object_type;
typedef struct object {
object_type type;
union {
struct {
char value;
} boolean;
struct {
long value;
} fixnum;
} data;
} object;
Now an object can hold two different values (a boolean or an integer), so the union now serves a purpose. The inner structures are still redundant, though. Notice how none of the code dealing with fixnums has to change.
I suspect that the inner structures are there just for parallelism. In v0.6, the author adds the pair type, which consists of a structure of two pointers.
You're correct. This is going to be a single type which can hold a number of different typed values.
This is the first step. The second step will be to add another type to this.
To do that, you'll add an type ID to the enum and add the value itself to the union, something like:
typedef enum {FIXNUM,FLOATNUM} object_type;
typedef struct object {
object_type type;
union {
struct { long value; } fixnum;
struct { float value; } floatnum;
} data;
} object;
As to the reason why you have single-field structures, my guess is that they're allowing for the possibility of multi-field structures later on:
typedef enum {FIXNUM,FLOATNUM,STRING} object_type;
typedef struct object {
object_type type;
union {
struct { long value; } fixnum;
struct { float value; } floatnum;
struct { size_t len; char *data; } string;
} data;
} object;
That's just supposition on my part, it will probably become clear as you advance through the iterations why they chose to do it that way.