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(¶ms)
{
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(¶ms)
{
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);
Related
I'm trying to figure out how to parse S-expressions in C on my own, in order to store data and code for my own rudimentary Lisp (written as a learning exercise, not for production).
Before explaining my code and my reasoning, I should explain that all I know about S-expressions is the introductory section of the Wikipedia article on it, and the occasional glance at Common Lisp code, so the naming of my structs and variables may be a bit off.
My language of implementation is C, and before I defined any functions I created the following structs:
typedef enum {
string,
letter,
integer,
} atom_type;
typedef struct {
void* blob;
atom_type type;
} atom;
typedef struct expr {
atom* current;
struct expr* next;
} expr;
Each atom is stored in a struct atom, which contains a enum instance (? I'm not sure of the correct jargon for this) and a void pointer pointing to the data to be stored. Each S-expression "node" consists of a pointer to an atom and a pointer to the next S-expression node.
I've written a rudimentary function that accepts a string and parses it into an atom, like the following:
atom* parse_term(char* str) {
size_t len = strlen(str);
atom* current = malloc(sizeof(atom));
if(str[0] == '\'') {
current->blob = (char*) &str[1];
current->type = letter;
} else if(str[0] == '\"') {
char temp[256];
int pos = 1;
while(str[pos] != '\"') {
temp[pos] = str[pos];
pos++;
}
current->blob = malloc(256 * sizeof(char));
current->blob = (char*) &temp;
current->type = string;
} else if(isdigit(str[0])){
char temp[256];
int pos = 0;
while(str[pos] != ' ') {
temp[pos] = str[pos];
pos++;
}
int tmp = atoi(temp);
current->blob = (int*) &tmp;
current->type = integer;
}
return current;
}
The function seems to be working correctly; at least, when I print out the data type it shows it correctly. But apart from this I can't figure out how to print out the actual 'blob': I've tried using the %p formatting code, as well as a switch statement:
void print_atom(atom* current) {
switch(current->type) {
case string:
printf("atom%s\ttype:%d", current->blob, current->type);
case letter:
printf("atom%c\ttype:%d", current->blob, current->type);
case integer:
printf("atom%c\ttype:%d", current->blob, current->type);
}
}
But this doesn't work. In the case of a string, it returns garbled text and in the case of everything else, it just doesn't print anything where the atom's information is supposed to be.
I imagine this is a product of my use of a void* within a struct; how could I remedy this? I think I did cast properly (though I could very well be wrong, please tell me), the only other option I could concieve of is storing a hardcoded variable for every supported data type in the 'atom' struct, but this seems wasteful of resources.
Don't use void*. Use a union. That's what unions are for.
In this example, I use an "anonymous union", which means that I can just refer to its fields as though they were directly inside the Atom struct. (I changed the spelling of names according to my prejudices, so that types are Capitalised and constants are ALLCAPS. I also separated the typedef and struct declarations for Atom, in case Atom turns out to be self-referential.
typedef enum {
STRING,
LETTER,
INTEGER
} AtomType;
typedef struct Atom Atom;
struct Atom {
union {
char* str;
char let;
int num;
};
AtomType type;
};
void print_atom(Atom* current) {
switch(current->type) {
case STRING:
printf("atom %s\ttype:%d", current->str, current->type);
case LETTER:
printf("atom %c\ttype:%d", current->let, current->tyoe);
case INTEGER:
printf("atom %d\ttype:%d", current->num, current->type);
}
}
As someone says in a comment, that's not actually how Lisp objects look. The usual implementation is combine cons cells and atoms, something like this (instead of AtomType). You'll also need to add CELL to your enum.
typedef struct Cell Cell;
struct Cell {
union {
char* str;
char let;
int num;
struct {
Cell* hd; // Historic name: car
Cell* tl; // Historic name: cdr
};
};
CellType type;
};
Here there's an anonymous struct inside an anonymous union. Some people say this is confusing. Others (me, anyway) say it's less syntactic noise. Use your own judgement.
The use of Cell* inside the definition of Cell is the motivation for typedef struct Cell Cell.
You can play not-entirely-portable-but-usually-ok games to reduce the memory consumption of Cell, and most real implementations do. I didn't, because this is a learning experience.
Also note that real Lisps (and many toy ones) effectively avoid most parsing tasks; the language includes character macros which effectively do what parsing is needed (which isn't much); for the most part, they can be implemented in Lisp itself (although you need some way to bootstrap).
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.
I have a bunch of global variables which are set through callback. I get notification for one of them at a time. I want to keep single function to update this state. This is version of how I am doing.
typedef struct {
int g_var_a;
char g_var_b;
double g_var_c;
long g_var_d;
} global_state_t;
typedef union {
int g_var_a;
char g_var_b;
double g_var_c;
long g_var_d;
} global_change_t;
typedef enum {
VAR_A;
VAR_B;
VAR_C;
VAR_D;
} global_change_type_t;
global_state_t gs = {0};
void udpate_global_state(global_change_t *c, global_change_type_t type) {
switch (type) {
case VAR_A: {
gs.g_val_a = c->g_var_a;
break;
}
...
....
}
}
This is called as:
callback() {
...
global_change_t c = {.g_var_a = 1234};
update_global_state(&c, VAR_A);
}
But to me this looks bad. There are three construct: struct, union, enum all of which have to be in sync. Isn't there a better way to do this ?
First I'll note that you can decrease maintenance risk by making your union with only one field per struct field type, not one field per field. You can also do tricks with macros to eliminate redundancies entirely. I can explain this further if you're interested.
You can also abstract away from the data with functions. Unfortunately to give them all the same signature you need either a union as you used or void pointers. I'll try the latter.
typedef struct {
int g_var_a;
char g_var_b;
double g_var_c;
long g_var_d;
} GLOBAL_STATE;
GLOBAL_STATE gs[1];
typedef void (*UPDATER)(void*);
void a_updater(void *val) { gs->g_var_a = *(int*)val; }
void b_updater(void *val) { gs->g_var_b = *(char*)val; }
void c_updater(void *val) { gs->g_var_c = *(double*)val; }
void d_updater(void *val) { gs->g_var_d = *(long*)val; }
void udpate_global_state(UPDATER updater, void *val) {
updater(val);
}
NB You should not used types ending in _t as these are reserved for system headers by the C Standard.
Now you can say
{
int i[1] = { 3 };
char c[1] = { 'a' };
double d[1] = { 1.234 };
long g[1] = { 123456 };
update_global_state(a_updater, i);
update_global_state(b_updater, c);
update_global_state(c_updater, d);
update_global_state(d_updater, g);
}
The 1-element array trick is purely esthetic. Drop it and use & in the update calls if you like. Both ways produce the same code.
Of course this is not type safe, but neither is your solution. It does reduce code structures that must be maintained in synch.
There's no elegant way to define run-time variants in C.
The 2 approaches include:
struct containing a union with actual value and some mechanism to dispatch based on actual type. In simple case this can be an enum tag, in more complicated cases there will be some function pointers storing references to the value_is() and get_value_as() methods (this later approach is mostly used in dynamic language interpreters).
Universal value type (most often a string) which can encode distinct variant values. The receiving function will then do some simple parsing to get the data out (this is essentially equivalent to struct with union and enum tag), but may result in more maintainable and readable programs at an expense of some (not that big) performance loss.
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.
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 *).