Multiple structs, same fields that need to be accessed in a method - c

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.

Related

Print out list of non-uniform parameters in C

I have some device with lot of different parameters, which could be bool, char, int, float, string and so on. I need to print them all at once in some AJAX array (for the web interface control). I have to use pure C, and also this code will be run on some MCU with narrow ROM/RAM resources. What is the possible ways to do it? If they there all uniform, like int’s, I could just use array:
Uint16_t params[PARAM_1]=GetParam(PARAM_1);
PrintParams(&params)
{
For(iii=0;iii<MAX_COUNT;iii++)
{
HTTPPrint(params[iii]);
}
}
But they are not.
Not grouping them at all will be prone to errors then adding/removing parameters, and also overhead:
Uint16_t param1= GetParam1();
Float param2= GetParam2();
PrintParams(&params)
{
HTTPPrint(param1);
HTTPPrint(param2);
//another 100+ parameters to print
}
Using some advanced data structure, like linked list will be huge overhead (for any singe char need to store 4-byte pointer at least).
Maybe there is another ways to do it?
Tagged union allows you to carry type information with the data and doesn't take a lot of space:
enum type_t {
kTypeChar = 1,
kTypeInt = 2
};
union data_t {
char i8;
int i32;
};
struct anytype {
enum type_t tag;
union data_t data;
};
You can directly do case-analysis on stored value type. Although it does leave some room for error in mismatching type tag and value:
struct anytype v = GetParam(PARAM_1);
switch (v->tag) {
case kTypeChar: HTTPPrintChar(v->data.i8); break;
case kTypeInt: HTTPPrintInt(v->data.i32); break;
default: assert(0);
};
Or you can add a polymorphic print handler into each type to make it less error prone. Although it will consume additional space to carry a pointer with all data items but it is kinda less prone to error and easier to use.
typedef void (*print_func_t) (struct polytype* self);
struct polytype {
print_func_t print;
union data_t data;
};
void print_char(struct polytype* self) {
HTTPPrintChar(self->data.i8);
}
void print_int(struct polytype* self) {
HTTPPrintChar(self->data.i32);
}
struct polytype t = GetParam(PARAM_1); /* GetParam sets proper print fptr based on param type */
t.print(&t);

Linked list with different types

How do I create a list where each element can be of a different type?
What I am doing now is something along these lines:
typedef struct listitem
{
int flavour;
void *payload;
struct listitem *next;
} listitem
And when accessing an item from this list, I check the value of flavour and then cast payload to the appropriate type. This approach seems a bit sledge-hammer to me.
What is the standard way to do this in C99?
Is there someway to infer the type of an object, given only its address?
No, C doesn't provide you with reflection facilities, i.e. the capability to infer the type of an object based on its address. You're going to have to manage that yourself. You're doing the right thing, but you're going to have to manage the flavour yourself. Others have pointed out how to lessen the pain by putting all the alternative types in a union, so that you don't have to cast all the time. You may be well off writing a few inline functions that hide all the unions and what not. To get an idea:
typedef struct listitem
{
int flavour;
union {
int i;
char * str;
};
struct listitem * next;
};
int int_item(struct listitem * item)
{
if (flavour != FLAVOUR_INT)
error("Not an integer");
return item->i;
}
char * string_item(struct listitem * item)
{
if (flavour != FLAVOUR_STRING)
error("Not a string");
return item->str;
}
Pointers you can just use a void *. Other types you can use a union:
typedef struct listitem
{
int flavour; // type of data held
union {
int i;
double d;
float f;
:
:
};
struct listitem *next;
} listitem
Sorry, I misread your question. You have manage flavour yourself.
There's another way.
If you don't have many value for your flavour you can embed it the address. An address aligned to a power of two has its least significant bits to 0.
In C11 you have a standard way of allocating aligned memory which can then be used to tag your pointers.

C generic type as function argument input

So I have two different structs in which all the properties that I will be accessing will be the same. and I also have a function, who's argument, i want to be able to accept either of the two. Example:
typedef struct{
int whatnot = 14;
int thing[11];
} TH_CONFIG;
typedef struct{
int whatnot = 3;
int thing[5];
} TH_CONFIG_2;
*_CONFIG var;
void fun(*_CONFIG input)
{
input.whatnot = 5;
}
int main(){
fun(var);
}
I may have an inkling that I should use void as the type from that I could typecast or something?, but my searching has only yielded things about function pointers, templates, and C#.
EDIT: *_CONFIG is not meant to be syntactically correct, its signifying that I don't know what to do there, but its supposed to be the _CONFIG type
Possible solutions.
Just use an array of length 11 for both of them. Did you really run out of those last 6 bytes on your OS?
Make it a dynamic array.
Just write in assembly, you clearly don't care about C's higher-level-ness.
Use a language like C++ that supports templates or polymorphism.
Just pass in the arguments of the struct you care about.
void fun(int* whatnot) {
*whatnot = 5;
}
int main() {
fun(&myStruct.whatnot);
return 0;
}
Factor into a quasi-OO design.
struct {
int whatnot;
} typedef Common;
struct TH_CONFIG_1 {
Common common;
int thing[11];
};
struct TH_CONFIG_2 {
Common common;
int thing[5];
}
But if you insist...
void fun(void* input) {
( (int)(*input) ) = 5;
}
or...
void fun(void* input) {
( (TH_CONFIG*) input)->whatnot = 5; // may have been a TH_CONFIG_2, but who cares?
}
Note: this would not pass code review at any C shop.
You can use any pointer type and cast it.
If all the properties you're accessing are the same, I'm guessing one's an extension of the other (since the properties need to have the same offset from the beginning of the struct). In that case you may want to use this pattern:
struct base {
int foo;
char **strings;
};
struct extended {
struct base super;
double other_stuff;
};
Since super is at the start of struct extended, you can cast a struct extended * to struct base * without problems. Of course, you could do that by repeating the same fields in the beginning of struct extended instead, but then you're repeating yourself.

C Variable Member List for structs, is this possible?

I have a question about structures having a "variable members list" similar to the "variable argument list" that we can define functions as having.
I may sound stupid or completely off the line in terms of C language basics, but please correct me if I am wrong.
So can I have a C struct like this:
struct Var_Members_Interface
{
int intMember;
char *charMember;
... // is this possible?
};
My idea is to have a c style interface that can be implemented by the classes but these classes can have additional members in this structure. However, they must have intMember and charMember.
Thanks in advance.
The closest approximation in C99 (but not C89) is to have a flexible array member at the end of the structure:
struct Var_Members_Interface
{
int intMember;
char *charMember;
Type flexArrayMember[];
};
You can now dynamically allocate the structure with an array of the type Type at the end, and access the array:
struct Var_Members_Interface *vmi = malloc(sizeof(*vmi) + N * sizeof(Type));
vmi->flexArrayMember[i] = ...;
Note that this cannot be used in C++.
But that isn't a very close approximation to what you are after. What you are after cannot be done in C with a single structure type, and can only be approximated in C++ via inheritance - see other answers.
One trick that you can get away with - usually - in C uses multiple structure types and lots of casts:
struct VM_Base
{
int intMember;
char *charMember;
};
struct VM_Variant1
{
int intMember;
char *charMember;
int intArray[3];
};
struct VM_Variant2
{
int intMember;
char *charMember;
Type typeMember;
};
struct VM_Variant3
{
int intMember;
char *charMember;
double doubleMember;
};
Now, with some sledgehammering casts, you can write functions which take 'struct VM_Base *' arguments, and pass in a pointer to any of the VM_VariantN types. The 'intMember' can probably be used to tell which of the variants you actually have. This is more or less what happens with the POSIX sockets functions. There are different types of socket address, and the structures have different lengths, but they have a common prefix, and the correct code ends up being called because the common prefix identifies the type of socket address. (The design is not elegant; but it was standard - a de facto standard from BSD sockets - before POSIX standardized it. And the BSD design pre-dates C89, let alone C99. Were it being designed now, from scratch, with no requirement for compatibility with existing code, it would be done differently.)
This technique is ugly as sin and requires casts galore to make it compile -- and great care to make it work correctly. You shouldn't bother with this sort of mess in C++.
You can't do anything like this with direct language support in C; but in C++, classes that extended your struct would inherit those data members and could add their own. So in C++, not only can you do this, but it's a normal mode of operation.
You first need to understand what a struct really is.
A struct in C is little more than a standard for interpreting bytes in memory.
To see what that means, let's use your struct:
struct Var_Members_Interface
{
int intMember;
char *charMember;
};
struct Var_Members_Interface instance; //An instance of the struct
What this means is, "I'll reserve some memory and call it instance, and I'll interpret the first few bytes to mean an integer, and the next few bytes to mean that the point to somewhere in memory."
Given this, it makes little sense to have "variable-member" structs, because a struct is just the layout specification for an existing block of memory -- and existing blocks don't have "variable" length.
You could do it the way the old X11 Xt widget library did it:
struct Var_Members_Interface {
int intMember;
char *charMember;
};
struct Other_Part {
int extraInt;
char *extraString;
}
struct Var_Other_Interface {
struct Var_Members_Interface base;
struct Other_Part other;
};
As long as you're careful with your allocations, alignment, and padding issues, then this will work:
struct Var_Other_Interface *other = create_other();
struct Var_Members_Interface *member = (struct Var_Other_Interface *)other;
struct Var_Other_Interface *back_again = (struct Var_Other_Interface)member;
And you can nest the structs as deep as needed to get a single inheritance hierarchy.
This sort of thing is not for the feint of heart: you have to be very careful with you allocations, structure nesting, etc.
Have a look at an old school Xt widget and you'll get the idea; Xt widgets were usually implemented in three files: a C source file, a public header with the function interface, and a private header to define the structure layout (this one would be needed for subclassing).
For example, the Ghostscript widget that I used to use in mgv looked like this:
typedef struct {
/* Bunch of stuff. */
} GhostviewPart;
typedef struct _GhostviewRec {
CorePart core;
GhostviewPart ghostview;
} GhostviewRec;
The CorePart was the standard Xt widget definition and the GhostviewRec was the actual widget itself.
Not exactly what you are looking for but you can create a void pointer within your struct that can be used to point to another struct where the new types are defined.
struct Var_Members_Interface
{
int intMember;
char *charMember;
void *otherMembers;
};
Edit: The solution in this article might be a lot closer to what you are looking for.
You have two choices I think. You can emulate what C++ does but unfortunately, you have to see all the gory details. You define your common base struct and have that as a member of all your variant structs e.g.
struct VM_Base
{
int intMember;
char *charMember;
};
struct VM_Variant1
{
struct VM_Base base;
int foo;
};
struct VM_Variant2
{
struct VM_Base base;
char *charMember;
double bar;
};
struct VM_Variant3
{
struct VM_Base base;
char *charMember;
char baz[10];
};
Pointers to any of the variant structs are also pointers to the base member of the variant struct so you can cast to the base member freely. Going back the other way is obviously more problematic, since you need a check to make sure you are casting to the right type.
You can do away with the casts by using union instead e.g.
struct VM_Variant1
{
struct VM_Base base;
int foo;
};
struct VM_Variant2
{
struct VM_Base base;
char *charMember;
double bar;
};
struct VM_Variant3
{
struct VM_Base base;
char *charMember;
char baz[10];
};
struct VM
{
int intMember;
char *charMember;
union
{
struct VM_Variant1 vm1;
struct VM_Variant2 vm2;
struct VM_Variant3 vm3;
}
};
This second method obviates the need for type casts. You access the members like this:
double aDouble = aVMStruct.vm2.bar;
The three members of the union overlay each other in memory so the allocated block will only be the size of the largest of the three variants.

typecheck for return value

I have a list in which i want to be able to put different types. I have a function that returns the current value at index:
void *list_index(const List * list, int index) {
assert(index < list->size);
return list->data[index];
}
In the array there are multiple types, for example:
typedef struct structA { List *x; char *y; List *z; } structA;
typedef struct structB { List *u; char *w; } structB;
Now in order to get data from the array:
structA *A;
structB *B;
for(j=0... ) {
A = list_index(list, j);
B = list_index(list, j);
}
But now how do I find out the type of the return value? Is this possible with typeof (I'm using GCC btw)?
And is this even possible or do i have to make some sort of different construction?
You'll have to use unions like shown here.
The best way to solve this would be to use unions.
Another way would be to memcpy() the list item to an actual struct (i.e., not a pointer) of the appropriate type. This would have the advantage of making each List item as small as possible.
A third way would be to just cast the pointer types as in type punning. C allows this as long as the object is dereferenced with its either its correct type or char.
Either way, you will need to put a code in each structure that identifies the type of object. There is no way the compiler can figure out what a pointer points to for you. And even if you could use typeof, you shouldn't. It's not C99.
Technically, if you don't use a union, you will have a problem making a legal C99 access to the type code, because you will need to make a temporary assumption about the type and this will violate the rule that objects must be dereferenced as their actual type, via a union, or via a char *. However, since the type code must by necessity be in the same position in every type (in order to be useful) this common technical violation of the standard will not actually cause an aliasing optimization error in practice.
Actually, if you make the type code a char, make it the first thing in the struct, and access it via a char *, I think you will end up with code that is a bit confusing to read but is perfectly conforming C99.
Here is an example, this passes gcc -Wall -Wextra
#include <stdio.h>
#include <stdlib.h>
struct A {
char typeCode;
int something;
};
struct B {
char typeCode;
double somethingElse;
};
void *getMysteryList();
int main()
{
void **list = getMysteryList();
int i;
for (i = 0; i < 2; ++i)
switch (*(char *) list[i]) {
case 'A':
printf("%d\n", ((struct A *) list[i])->something);
break;
case 'B':
printf("%7.3f\n", ((struct B *) list[i])->somethingElse);
break;
}
return 0;
}
void *getMysteryList()
{
void **v = malloc(sizeof(void *) * 2);
struct A *a = malloc(sizeof(struct A));
struct B *b = malloc(sizeof(struct B));
a->typeCode = 'A';
a->something = 789;
b->typeCode = 'B';
b->somethingElse = 123.456;
v[0] = a;
v[1] = b;
return v;
}
C handles types and typing entirely at compile time (no dynamic typing), so once you've cast a pointer to a 'void *' its lost any information about the original type. You can cast it back to the original type, but you need to know what that is through some other method.
The usual way to do this is with some kind of type tag or descriptor in the beginning of all the objects that might be stored in your list type. eg:
typedef struct structA { int tag; List *x; char *y; List *z; } structA;
typedef struct structB { int tag; List *u; char *w; } structB;
enum tags { structAtype, structBtype };
You need to ensure that every time you create a structA or a structB, you set the tag field properly. Then, you can cast the void * you get back from list_index to an int * and use that to read the tag.
void *elem = list_index(list, index)
switch (*(int *)elem) {
case structAtype:
/* elem is a structA */
:
case structBtype:
/* elem is a structB */
Make the elements you want to put into the list all inherit from a common base class. Then you can have your base class contain members that identify the actual type.
class base {
public:
typedef enum {
type1,
type2,
type3
} realtype;
virtual realtype whatAmI()=0;
};
class type_one : public base {
public:
virtual base::realtype whatAmI() { return base::type1; };
};
class type_two : public base {
public:
virtual base::realtype whatAmI() { return base::type2; };
};
After that, you'd declare your list type like:
std::list<base *> mylist;
and you can stuff pointers to any of the derived types into the list. Then when you take them out, you can just call 'whatAmI()' to find out what to cast it to.
Please note: Trying to do this in C++ means you are doing something in a way that's not a good match for C++. Any time you deliberately evade the C++ type system like this, it means you're giving up most of the usefulness of C++ (static type checking), and generally means you're creating large amounts of work for yourself later on, not only as you debug the first iteration of this app, but especially at maintenance time.
You have some choices. Keep in mind that C is basically not a dynamically typed language.
You Make a common base for the structs, and put a simple type indicator of your own in it.
struct base {
int type_indication:
};
then
struct structA {
struct base base;
...
};
and then you can cast the pointer to (struct base *).

Resources