Function to look though any struct in C - c

I have a struct with variety of data types. I want to create a universal function
that can:
look through any struct and check if the item values are within
certain range for given types: (E.G. item 1 should be within 10~35,
item 3 should be either 0/1). Note that the struct's item types and
names are not passed to the function, just the struct(any struct)
Count how many items are in the struct given any structure
Example:
typedef struct _anyStruct_t
{
uint8_t item1;
uint16_t item2;
bool item3;
char item4;
}anyStruct_t

What you are asking for is effectively impossible in C.
First of all, struct types contain no metadata about their contents. At runtime, a struct object is just a sludge of bytes. There's no way to determine at runtime the number or types of members in a struct object.
Secondly, if you want to do this for any struct type, you will have to pass its address to the function as a void *, meaning you have no way of knowing whether it's a struct type at all.
You would basically have to create your own "class" type that a) stores metadata about its members and b) supports some form of inheritance such that you can pass a pointer to the base "class" type and use that to access the metadata and members.
IOW, you'd have to re-implement a good chunk of C++.
Edit
Actually, as Andrew mentions below, even C++ doesn't support reflection. You'd have to go even further.

As others have said, C doesn't support reflection and so there is no universal way to figure out what attributes exist in C data structure.
In the past I've seen folks write a meta-compiler which from some description language can be taught to generate C data structures and accessor methods.
Usually this is done if you're trying to write code that will iterate over and fill in data structures without needing to know all the details of the structures being processed - this can be useful in building messaging frameworks. But always feels cumbersome because some of your source code files are generated at build time (think lex and yacc).
Of course the other application for something like this is gdb. In that case the compiler, given '-g', generates the metadata about the data structures and embeds that in it the stabs (or gstabs, or some other) information in the object file. Your program could use /proc/self/ to find its object code on disk, open it and process through all of the stabs info. While clever, that would be very platform specific and probably pretty brittle.

look through any struct and check if the item values are within certain range for given types: (E.G. item 1 should be within 10~35, item 3 should be either 0/1). Note that the struct's item types and names are not passed to the function, just the struct(any struct)
This is not possible in C. If you only have a pointer to an unknown struct, there is no way to find out which fields the struct has.

As mentioned, one needs more information about what is in the struct. C, as opposed to C++, etc, wasn't designed around this abstraction. However, it's not impossible; nothing is stopping one from defining one's own virtual table.
#include <stdlib.h> /* EXIT rand */
#include <string.h> /* strcpy */
#include <stdio.h> /* sprintf, printf */
#include <assert.h> /* assert */
#include <stdint.h> /* (C99) uint8_t uint16_t */
#include <stdbool.h> /* (C99) bool */
union AllTypes {
bool boolean;
char letter;
uint8_t byte;
uint16_t word;
};
/* `is_valid` functions. */
static bool is_valid_boolean(const union AllTypes all) {
/* Not sure this will ever be false. */
return all.boolean == true || all.boolean == false;
}
static bool is_valid_letter(const union AllTypes all) {
return (all.letter >= 'a' && all.letter <= 'z')
|| (all.letter >= 'A' && all.letter <= 'Z');
}
static bool is_valid_byte(const union AllTypes all) {
return all.byte <= 35 && all.byte >= 10;
}
static bool is_valid_word(const union AllTypes all) {
return all.word < 1000;
}
/* `to_string` functions */
static void boolean_to_string(const union AllTypes all, char (*const a)[12]) {
strcpy(*a, all.boolean ? "true" : "false");
}
static void letter_to_string(const union AllTypes all, char (*const a)[12]) {
sprintf(*a, "'%c'", all.letter);
}
static void byte_to_string(const union AllTypes all, char (*const a)[12]) {
sprintf(*a, "b%u", all.byte);
}
static void word_to_string(const union AllTypes all, char (*const a)[12]) {
sprintf(*a, "w%u", all.word);
}
typedef void (*ToString)(const union AllTypes all, char (*const a)[12]);
/* The virtual-table. */
static const struct VTable {
ToString to_string;
bool (*is_valid)(const union AllTypes);
} vt_boolean = { &boolean_to_string, &is_valid_boolean },
vt_letter = { &letter_to_string, &is_valid_letter },
vt_byte = { &byte_to_string, &is_valid_byte },
vt_word = { &word_to_string, &is_valid_word };
/* The data has an extra `vt`; this would be implicit in C++. */
struct Data {
const struct VTable *vt;
union AllTypes all;
};
static void to_string(const struct Data *const data, char (*const a)[12]) {
data->vt->to_string(data->all, a);
}
static bool is_valid(const struct Data *const data) {
return data->vt->is_valid(data->all);
}
/* Testing. */
static void fill(struct Data *const data) {
assert(data);
switch(rand() / (RAND_MAX / 4 + 1)) {
case 0: data->vt = &vt_boolean;
data->all.boolean = rand() / (RAND_MAX / 2); break;
case 1: data->vt = &vt_letter;
data->all.letter = rand() / (RAND_MAX / 26 + 1) + 'a'; break;
case 2: data->vt = &vt_byte;
data->all.byte = rand() / (RAND_MAX / 25 + 1) + 10; break;
case 3: data->vt = &vt_word;
data->all.word = rand() / (RAND_MAX / 999 + 1); break;
}
}
int main(void) {
struct Data data[32], *d, *const d_end = data + sizeof data / sizeof *data;
char a[12];
/* Fill the data with random values. */
for(d = data; d < d_end; d++) {
fill(d);
if(!is_valid(d)) return fprintf(stderr, "Impossible!\n"), assert(0),
EXIT_FAILURE;
}
/* Print. */
fputs("{ ", stdout);
for(d = data; d < d_end; d++) {
if(d != data) fputs(", ", stdout);
to_string(d, &a);
fputs(a, stdout);
}
fputs(" }.\n", stdout);
return EXIT_SUCCESS;
}
Prints out on my machine,
{ false, w458, b15, true, b33, 'n', w34, true, b10, 'b', 'r', b33,
w526, true, 's', w761, 'b', b18, b28, w364, true, b28, b11, b32, 'l',
w477, false, 'e', 'x', w60, w504, b17 }.

Related

How to create prototype that references a double located with in a struct located within a linked list?

I'm currently creating a program to interpolate linear regressions on missing entries in a time series. IE Col 2 Row 20-30 is missing the program would take col 2 row 19 (for instance 10) and col 2 row 30 (20) then fill in the NULL values linearly ie 11, 12, 13. I have multiple columns which have NULL values, so to do this I want to create a struct
struct missingPoint
{
double lastVal;
struct node * ptrtoLast;
int missingVals;
};
struct point
{
double col1;
double col2;
double col3;
};
typdef struct point Tick;
typedef struct node
{
Tick tick;
struct node * next;
} Node;
typedef Node * List;
So the idea is to write a prototype then a function which takes *ptrtoList->tick.colx as an argument as well as the missingPoint struct then I can iterate it the col and fill in the missing time series data, it iterates the column storing ptrs to nodes which contain non-NULL entries for the Col, when it hits a NULL val, it has the ptr to the last node with non-null val, it iterates until it gets a non-Null value again then using the ptr it has stored in memory it iterates back through and replaces the Null values with a linear regression between the two poitns. But I don't know how I can specify a double which occurs inside a struct which is pointed to by another struct for a function and function prototype, with that function I could just call the function for every column I have, without it I'd have to hardcode quite a bit which I'd like to avoid. Any advice would be greatly appreciated.
So the function would be like this, this currently has the column hard coded, I'd like to pass the column number as an argument so that I can multithread it, and call the function multiple times since the matrices I'm looking at are quite big, and because I'd like to practice concurrent programming:
void crawlOne(List *plist)
{
Node * last;
double lastVal, tmp;
int i, count = 0;
Node * pnode = *plist;
while(pnode != NULL)
{
last = pnode->next;
pnode = pnode->next;
if(pnode->tick.col1=NULL)
{
while(pnode->tick.col1=NULL)
{
count ++;
pnode = pnode->next;
}
tmp = lastVal-pnode->tick.col1;
pnode = last;
for(i=0;i<count;i++)
{
pnode = pnode->next;
pnode->tick.col1 = lastVal + i*(tmp/count);
i++;
}
}
}
}
Generally: Just define the function multiple times. No, C doesn't have templates.
The best: Generalize your data by providing an interface to manipulate it via function pointers - such interface is typically a virtual table. In your case a single function pointer to access the underlying data by a read/write handle looks enough. This effectively pulls the variant/changing/non-constant parts of the function into a different place. Allow users to pass an additional generic argument so that users can pass custom context:
void crawlOne(List *plist, double *(*getcol)(void *arg, struct point *p), void *arg)
{
// tmp = lastVal-pnode->tick.col1;
double tmp = *getcol(arg, &lastVal-pnode->tick);
...
// pnode->tick.col1 = lastVal + i*(tmp/count);
*getcol(arg, &pnode->tick) = lastVal + i*(tmp/count);
...
}
double *point_getCol1(void *arg, struct point *p) {
return &p->col1;
}
double *point_getCol2(void *arg, struct point *p) {
return &p->col2;
}
double *point_getCol3(void *arg, struct point *p) {
return &p->col3;
}
int main() {
crawlOne(plist, point_getCol2, NULL);
crawlOne(plist, point_getCol3, NULL);
}
In your case you can pass offsetof to members in point and dereference a pointer to double* at proper positions. This is not flexible and invites bugs, because it doesn't statically check types:
void crawlOne(List *plist, size_t coloffset)
{
...
// tmp = lastVal-pnode->tick.col1;
double tmp = *(double*)((char*)&lastVal-pnode->tick + coloffset);
...
// pnode->tick.col1 = lastVal + i*(tmp/count);
*(double*)((char*)&pnode->tick + coloffset) = lastVal + i*(tmp/count);
...
}
int main() {
crawlOne(plist, offsetof(struct point, col1));
crawlOne(plist, offsetof(struct point, col2));
}
It's common to use a macro to ease up defining the function multiple times (only do if you really know what you are doing). Such tends to become hard to maintain, and is hard to debug:
#define DECLARE_CRAWL_ONE(FUNC, MEMBER) \
void FUNC(List *plist) \
{ \
/* tmp = lastVal-pnode->tick.col1; */ \
double tmp = lastVal-pnode->tick.MEMBER; \
... \
/* pnode->tick.col1 = lastVal + i*(tmp/count); */ \
lastVal-pnode->tick.MEMBER = lastVal + i*(tmp/count); \
... \
}
DECLARE_CRAWL_ONE(crawlOnecol1, col1)
DECLARE_CRAWL_ONE(crawlOnecol2, col2)
DECLARE_CRAWL_ONE(crawlOnecol2, col2)
So to summarize:
You have a function crawlOne(List *plist) that locates some objects of type struct point and does something to their col1 members.
You would like to have a function crawlSome(List *plist, int colnum) which:
when called as crawlSome(list, 1) operates on col1
when called as crawlSome(list, 2) operates on col2
and so on.
By far the cleanest approach, as John Bollinger suggested in a comment, is to redesign struct point to contain an array instead of three separate members:
struct point {
double col[3];
};
void crawlSome(List *plist, int colnum) {
// ...
pnode->tick.col[colnum] = ...;
}
This does mean that you have to change all existing code that uses struct point, which although straightforward could be tedious, but in the long term you have a cleaner and more efficient design. I would do this if at all possible.
If you really cannot change the definition of struct point (e.g. it is used by third-party code that you can't modify), then you can't avoid hardcoding the member names somehow, since the names don't exist at runtime. KamilCuk has suggested some options for this. Another that I might think of is to pull out the hardcoding into a "column selector" function, so that it only has to be done at one place in your program. It should not be too inefficient if it can be inlined.
inline double *select_column(struct point *pt, int colnum) {
switch (colnum) {
case 1: return &pt->col1;
case 2: return &pt->col2;
case 3: return &pt->col3;
default: abort(); // or perhaps return NULL;
}
}
void crawlSome(List *plist, int colnum) {
// ...
*select_column(&pnode->tick, colnum) = ...
}
This avoids the need to duplicate the code of crawlOne at all, with or without a macro.
If you want to reduce the repetition in defining select_column, you can use a macro with token pasting:
inline double *select_column(struct point *pt, int colnum) {
switch (colnum) {
#define DO(N) case N: return &pt->col ## N ;
DO(1)
DO(2)
DO(3)
#undef DO
default: abort(); // or perhaps return NULL;
}
}
If you want to make the selector a little nicer to use, you can wrap it in a macro:
#define COL(p, n) (*select_column(&(p), (n)))
void crawlSome(List *plist, int colnum) {
// ...
COL(pnode->tick, colnum) = ...;
}
Alternatively, a similar approach can be implemented with offsetof, though with the same lack of type checking that KamilCuk points out:
#include <stddef.h>
const size_t col_offsets[3] = {
offsetof(struct point, col1),
offsetof(struct point, col2),
offsetof(struct point, col3)
};
#define COL(p, n) (*(double *)((char *)&(p) + col_offsets[(n)]))

Variabe type for variable inside function

I'm having different different types of structs, which are going to be passed to a function which performs the same tasks on them.
int menu_parameter_arrow_print(game_setting_identifier* identifier, controller_direction direction, uint8_t position)
{
if((position > setting->alternatives_number) || position < 0)
{
#ifdef OLED_PRINT_DEBUG_ENABLE
OLED_debug_print("Out of bounds");
#endif
return RETURN_VALUE_FAILURE;
}
else
{
switch ((int)*identifier)
{
case ((int) GAME_SETTING_ANALOG):
game_setting_analog* setting = (game_setting_analog*)&identifier;
case ((int) GAME_SETTING_TOGGLE):
game_setting_toggle* setting = (game_setting_toggle*)&identifier;
case ((int) GAME_SETTING_VALUE):
game_setting_value* setting = (game_setting_value*)&identifier;
}
This function gives a conflicting type-error
The operations performed on the structs are the same, but the structs contains different types of members:
struct game_setting_analog
{
//Identifier for the game-setting type:
game_setting_identifier identifier;
//Alternatives:
char* alternatives[4];
};
typedef struct game_setting_value game_setting_value;
struct game_setting_value
{
game_setting_identifier identifier;
uint8_t* alternatives[6];
uint8_t alternatives_number;
};
typedef struct game_setting_toggle game_setting_toggle;
struct game_setting_toggle
{
//Identifier for the game-setting type:
game_setting_identifier identifier;
toggle_state* alternatives[2];
};
typedef struct game_setting_difficulty game_setting_difficulty;
struct game_setting_difficulty
{
game_setting_identifier identifier;
char* alternatives[3];
};
Actions will be performed on the 'alternatives'-member of the structs, even though these members are of different types.
Is there a solution to doing this without having to use one if-statement for each identifier?
Edit: With a modification to the switch-case, I'm able to get the initialization compiled. The variables inside the switch-scope is however not visible to the rest of the function
int menu_print_parameter_line(game_setting_identifier* identifier, controller* C, uint8_t position)
{
uint8_t next_position = position;
controller_direction previous_direction = C->joystick.generalDirection;
if ((identifier == NULL) || (C == NULL) || (position == NULL))
{
return -1;
}
switch((int) identifier)
{
case ((int) GAME_SETTING_ANALOG):
{
game_setting_analog* setting = (game_setting_analog*)identifier;
uint8_t alternatives_number = 4;
}
break;
case ((int) GAME_SETTING_TOGGLE):
{
game_setting_toggle* setting = (game_setting_toggle*)identifier;
uint8_t alternatives_number = 2;
}
break;
case ((int) GAME_SETTING_VALUE):
{
game_setting_value* setting = (game_setting_value*)identifier;
uint8_t alternatives_number = setting->alternatives_number;
}
break;
default:
{
return -1;
}
break;
}
#ifdef MENU_PARAMETER_ASSIGNMENT_DEBUG
OLED_debug_print("before switch-case");
#endif
switch (previous_direction)
{
case LEFT:
next_position -= 1;
if(next_position <= 0)
{
next_position = alternatives_number;
}
I personally don't like the inheritance model that depends on the first member of the structure, like the BSD socket library is using. Basically you are just trying to implement std::variant from c++ in C.
Is there a solution to doing this without having to use one if-statement for each identifier?
The object-oriented concept of interface works very nice and I believe is applicable in this case. It takes some C discipline to write it, but it works like a charm and you could be looking for it here.
I copied your definitions from which I removed typedefs because I don't like them:
struct game_setting_analog {
char* alternatives[4];
};
struct game_setting_value {
uint8_t* alternatives[6];
uint8_t alternatives_number;
};
struct game_setting_toggle {
toggle_state* alternatives[2];
};
struct game_setting_difficulty {
char* alternatives[3];
};
Let's first implement the interface abstraction with a function pointer that allows to get the alternatives number:
// forward definition
struct game_setting_s;
// the virtual table for game_settings
struct game_setting_vtable_s {
uint8_t (*get_alternatives_number)(struct game_setting_s *t);
// TODO: add other members, constructor, copy constructor, destructor, etc.
};
// represents any game_setting
// exposes a public interface to access and manipulate a game_setting
struct game_setting_s {
// the vtable is const, so it can save RAM
const struct game_setting_vtable_s *v;
// this is a pointer to private settings data
void *data;
};
// accessor for less (or more ;) typing
static inline
uint8_t game_setting_get_alternatives_number(struct game_setting_s *t) {
// alternative you could pass t->data to the function, I pass it all
// so that functions can modify the t->data member
// and also so that advanced functions usages can use like container_of macros
return t->v.get_alternatives_number(t);
}
Then you need to provide the virtual tables for each of the types. The definitions can be in separate types, so you can have a separate .c/.h file pair for each of the type, just exposing public interface.
// game_setting_analog --------------------
static
uint8_t game_setting_analog_get_altenatives_number(struct game_setting_s *t)
{
return 4;
}
const struct game_setting_vtable_s game_setting_analog_vtable = {
.get_alternatives_number = game_setting_analog_get_altenatives_number,
};
// game_setting_toggle --------------------
static
uint8_t game_setting_toggle_get_altenatives_number(struct game_setting_s *t) {
struct game_setting_toggle *data = t->data;
return data->alternatives_number;
}
const struct game_toggle_vtable_s game_setting_toggle_vtable = {
.get_alternatives_number = game_setting_toggle_get_altenatives_number,
};
// and so on...
Then your function takes just the interface and is very clear without any switch case:
int some_function_that_needs_to_know_which_setting_is_passed(struct game_setting_s *s) {
int number_of_alternatives = game_setting_get_alternatives_number(s);
}
Remember to construct the interface object properly and watch who owns the memory of the object. Let's construct a toggle and call out function:
struct game_settting_toggle memory;
// your function to initialize the toggle
game_setting_toggle_intialize(&memory);
// the interface is constructed with the proper vtable
// and a pointer to proper memory region with the data
struct game_setting_s any_setting = {
.vtable = game_setting_toggle_vtable,
.data = &memory,
};
// the initailize function could be in interface too
// so you would just call game_setting_initialize(&any_setting);
// with usage of dynamic allocation, you can just ex.
// struct game_setting_s *any_setting = game_setting_new_toggle();
// and write proper object-oriented factories
// finally call our function.
some_function_that_needs_to_know_which_setting_is_passed(&any_setting);
Case labels do not provide scopes for variables. All three setting variables within the switch have different types which are the conflicts the compiler. Use brackets to define scopes:
switch ((int)*identifier)
{
case ((int) GAME_SETTING_ANALOG):
{
game_setting_analog* setting = (game_setting_analog*)&identifier;
}
case ((int) GAME_SETTING_TOGGLE):
{
game_setting_toggle* setting = (game_setting_toggle*)&identifier;
}
case ((int) GAME_SETTING_VALUE):
{
game_setting_value* setting = (game_setting_value*)&identifier;
}
}
Also, you're not breaking in the cases, so the code in all three cases are run if ((int)*identifier == (int) GAME_SETTING_ANALOG)

How to protect enum assignment

I want to prevent invalid value enum assignment. I know if i even assign value that is not in enum it will work. Example:
enum example_enum
{
ENUM_VAL0,
ENUM_VAL1,
ENUM_VAL2,
ENUM_VAL3
};
void example_function(void)
{
enum example_enum the_enum = ENUM_VAL3; // correct
the_enum = 41; // will work
the_enum = 0xBADA55; // also will work
bar(the_enum); // this function assumes that input parameter is correct
}
Is there easy, efficient way to check if assignment to enum is correct? I could test value by function
void foo(enum example_enum the_enum)
{
if (!is_enum(the_enum))
return;
// do something with valid enum
}
I could resolve this in following way:
static int e_values[] = { ENUM_VAL0, ENUM_VAL1, ENUM_VAL2, ENUM_VAL3 };
int is_enum(int input)
{
for (int i=0;i<4;i++)
if (e_values[i] == input)
return 1;
return 0;
}
For me, my solution is inefficient, how can i write this if i have more enums and more values in enums?
As long as the enum is continuous one can do something like this:
static int e_values[] = { ENUM_VAL0, ENUM_VAL1, ENUM_VAL2, ENUM_VAL3, ENUM_VAL_COUNT };
int is_enum(int input) { return 0 <= input && input < ENUM_VAL_COUNT; }
Another alternative is to not validate the enum value beforehand, but error out once the code detects an invalid value:
switch(input) {
case ENUM_VAL0: ... break;
case ENUM_VAL1: ... break;
...
default:
assert(0 && "broken enum");
break;
}
But there is no way to enforce that the enum value doesn't go out of the range at all in C. The best you can do if you want to secure the enum against fiddling is to hide the value away in a struct and then have functions to manipulate the struct. The function and struct implementation can be hidden away from the user via a forward declaration in the .h file and the implementation in the .c file:
struct example_t {
enum example_enum value;
}
void example_set_val0(example_t* v) { v->value = ENUM_VAL0; }
There is no way of warning about assigning integers that fit into the enum.
Enumerators in C are synonyms for integer types. Assuming the type chosen for enum example_enum is int, then your code is identical to:
void example_function(void)
{
int the_enum = ENUM_VAL3; // correct
the_enum = 12345; // will work
bar(the_enum); // this function assumes that input parameter is correct
}
void foo(int the_enum)
{
if (!is_enum(the_enum))
return;
// do something with valid enum
}
You could use structures, but even that can be circumvented:
struct example_enum_struct e = { 12345 };
e.value = 23456;
Basically if you want to restrict a type to specific values, you will need to perform checks.
If anyone is interested in this topic, here I have some solution which works.
typed_enums.h
#ifndef TYPED_ENUMS_H
#define TYPED_ENUMS_H
#define TYPED_ENUM(name_) \
typedef struct { int v; } name_
#define TYPED_ENUM_VALUE(name_, value_) (name_) { value_ }
#define GET_TYPED_ENUM_VALUE(en_) (en_.v)
#define TYPED_ENUM_EQ(a_, b_) (GET_TYPED_ENUM_VALUE(a_) == GET_TYPED_ENUM_VALUE(b_))
#endif
usb_class.h
#ifndef USB_CLASS_H
#define USB_CLASS_H
#include "typed_enums.h"
TYPED_ENUM(UsbClass);
#define USB_CLASS_BILLBOARD TYPED_ENUM_VALUE(UsbClass, 0x11)
#define USB_CLASS_TYPE_C_BRIDGE TYPED_ENUM_VALUE(UsbClass, 0x12)
#define USB_CLASS_DIAGNOSTIC_DEVICE TYPED_ENUM_VALUE(UsbClass, 0xDC)
#define USB_CLASS_WIRELESS_CONTROLLER TYPED_ENUM_VALUE(UsbClass, 0xE0)
#endif
usb_class_example.c
#include "typed_enums.h"
#include "usb_class.h"
#include <stdio.h>
int main(int argc, char ** argv)
{
UsbClass usbClass = USB_CLASS_WIRELESS_CONTROLLER;
usbClass = 12345; // tadam!!!! throws error
usbClass = USB_CLASS_VIDEO;
if (TYPED_ENUM_EQ(usbClass, USB_CLASS_VIDEO)) {
printf("usbClass = USB_CLASS_VIDEO\n");
}
printf("usb class value: %02X\n", GET_TYPED_ENUM_VALUE(usbClass));
return 0;
}
Pros:
enum value assignment works like struct assignment
enum for pointers also works
enum value can't be changed
Cons:
can't be used in switch
can't be directly compared
can't directly return enum number value
Note: sorry for abusing preprocessor here

How to use global variables on a state machine

I made this state machine :
enum states { STATE_ENTRY, STATE_....} current_state;
enum events { EVENT_OK, EVENT_FAIL,EVENT_REPEAT, MAX_EVENTS } event;
void (*const state_table [MAX_STATES][MAX_EVENTS]) (void) = {
{ action_entry , action_entry_fail , action_entry_repeat }, /*
procedures for state 1 */
......}
void main (void){
event = get_new_event (); /* get the next event to process */
if (((event >= 0) && (event < MAX_EVENTS))
&& ((current_state >= 0) && (current_state < MAX_STATES))) {
state_table [current_state][event] (); /* call the action procedure */
printf("OK 0");
} else {
/* invalid event/state - handle appropriately */
}
}
When I modify a global variable in one state the global variable remain the same , and I need that variable in all the states . Do you now what could be the problem ?
My Global variable is this structure:
#if (CPU_TYPE == CPU_TYPE_32)
typedef uint32_t word;
#define word_length 32
typedef struct BigNumber {
word words[64];
} BigNumber;
#elif (CPU_TYPE == CPU_TYPE_16)
typedef uint16_t word;
#define word_length 16
typedef struct BigNumber {
word words[128];
} BigNumber;
#else
#error Unsupported CPU_TYPE
#endif
BigNumber number1 , number2;
Here is how I modify:
//iterator is a number from where I start to modify,
//I already modified on the same way up to the iterator
for(i=iterator+1;i<32;i++){
nr_rand1=661;
nr_rand2=1601;
nr_rand3=1873;
number2.words[i]=(nr_rand1<<21) | (nr_rand2<<11) | (nr_rand3);
}
This is just in case you may want to change your approach for defining the FSM. I'll show you with an example; say you have the following FSM:
You may represent it as:
void function process() {
fsm {
fsmSTATE(S) {
/* do your entry actions heare */
event = getevent();
/* do you actions here */
if (event.char == 'a') fsmGOTO(A);
else fsmGOTO(E);
}
fsmSTATE(A) {
event = getevent();
if (event.char == 'b' || event.char == 'B') fsmGOTO(B);
else fsmGOTO(E);
}
fsmSTATE(B) {
event = getevent();
if (event.char == 'a' ) fsmGOTO(A);
else fsmGOTO(E);
}
fsmSTATE(E) {
/* done with the FSM. Bye bye! */
}
}
}
I do claim (but I believe someone will disagree) that this is simpler, much more readable and directly conveys the structure of the FSM than using a table. Even if I didn't put the image, drawing the FSM diagram would be rather easy.
To get this you just have to define the fsmXXX stuff as follows:
#define fsm
#define fsmGOTO(x) goto fsm_state_##x
#define fsmSTATE(x) fsm_state_##x :
Regarding the code that changese number2:
for(i=iterator+1;i<32;i){
nr_rand1=661;
nr_rand2=1601;
nr_rand3=1873;
number2.words[i]=(nr_rand1<<21) | (nr_rand2<<11) | (nr_rand3);
}
I can't fail to note that:
i is never incremented, so just one element of the array is changed (iterator+1) over an infinite loop;
even if i would be incremented, only the a portion of the words array it's changed depending on the value of iterator (but this might be the intended behaviour).
unless iterator can be -1, the element words[0] is never changed (again this could be the intended behaviour).
I would check if this is really what you intended to do.
If you're sure that it's just a visibility problem (since you said that when you declare it as local it worked as expected), the only other thing that I can think of is that you have the functions in one file and the main (or where you do your checks) in another.
Then you include the same .h header in both files and you end up (due to the linker you're using) with two different number2 because you did not declare it as extern in one of the two files.
Your compiler (or, better, the linker) should have (at least) warned you about this, did you check the compilation messages?
This is not an answer - rather it is a comment. But it is too big to fit the comment field so I post it here for now.
The code posted in the question is not sufficient to find the root cause. You need to post a minimal but complete example that shows the problem.
Something like:
#include<stdio.h>
#include<stdlib.h>
#include <stdint.h>
typedef uint32_t word;
#define word_length 32
typedef struct BigNumber {
word words[4];
} BigNumber;
BigNumber number2;
enum states { STATE_0, STATE_1} current_state;
enum events { EVENT_A, EVENT_B } event;
void f1(void)
{
int i;
current_state = STATE_1;
for (i=0; i<4; ++i) number2.words[i] = i;
}
void f2(void)
{
int i;
current_state = STATE_0;
for (i=0; i<4; ++i) number2.words[i] = 42 + i*i;
}
void (*const state_table [2][2]) (void) =
{
{ f1 , f1 },
{ f2 , f2 }
};
int main (void){
current_state = STATE_0;
event = EVENT_A;
state_table [current_state][event] (); /* call the action procedure */
printf("%u %u %u %u\n", number2.words[0], number2.words[1], number2.words[2], number2.words[3]);
event = EVENT_B;
state_table [current_state][event] (); /* call the action procedure */
printf("%u %u %u %u\n", number2.words[0], number2.words[1], number2.words[2], number2.words[3]);
return 0;
}
The above can be considered minimal and complete. Now update this code with a few of your own functions and post that as the question (if it still fails).
My code doesn't fail.
Output:
0 1 2 3
42 43 46 51

How to make struct members private?

I define a structure in a header file like so:
typedef struct {
void *data;
} point;
I want to keep other people from accessing *data directly, so I thought I'd declare the structure in the .c file instead and use something like extern typedef struct point; in the header file. That doesn't work however.
What's the best way to achieve this?
In your (public) header file:
typedef struct point point;
In your .c file:
struct point
{
void *data;
};
Note that users of your code will no longer be able to create a point on the stack, as the compiler doesn't know how big it is. You may have to provide a point_create() function which allocates memory and returns its address to the caller.
Use C++
Since jokes seem not be allowed here is the pure C version.
As another commenter pointed out if you really want to protect your internals from users of your Api you have seen and used plenty of such Apis. This Apis are e.g. the Windows or Linux user mode Apis. There you create kernel objects to which you never shall have access to. The Apis to deal with kernel objects use a synthetic construct called handle which is not simply a pointer to your own object but instead it is an index to an array where the kernel has stored the relevant meta data for your object.
You can use the same idea for your Apis as well.
Here for example is a C-Style public Api:
// Public.h
#include <stdlib.h>
typedef enum
{
None = 0,
PointType = 1
} Types;
typedef int Handle;
Handle CreateType(Types type);
int DeleteType(Handle object);
void IncrementX(Handle point);
void PrintPoint(Handle point);
As you can see you have generic methods which create and delete your objects which are defined here in an enum. Your methods which use the object will then need to lookup the integer handle to get the meta data object where the real data is stored.
This design is not very efficient if the objects you manage are small since for every object a second object is need which stores the object type, handle value and the pointer to the real data.
But you get much stronger safety guarantees such as
Type safety
Invalid handles are easy to find
Double free is impossible since you can manage the free state in the meta object
A typical usage of your Api might look like this:
Handle h = CreateType(PointType);
IncrementX(h);
IncrementX(h);
PrintPoint(h);
DeleteType(h);
And there is the super secret implementation in private.cpp where the Handle lookup array and some helper methods exist:
// Private.C
#include "stdafx.h"
#include <stdlib.h>
#include <Windows.h> // for ZeroMemory
#include "Public.h"
typedef struct
{
LPVOID pData;
Types type;
Handle handle;
} HandleInfo;
typedef struct
{
int x;
int y;
} Point;
HandleInfo *pAllocated;
int HandleBuffer = 0xffff;
unsigned char bInit = 0;
HandleInfo *GetFreeHandle()
{
int i;
if( !bInit )
{
pAllocated = (HandleInfo *) malloc(sizeof(HandleInfo)*HandleBuffer);
bInit = 1;
ZeroMemory(pAllocated, sizeof(HandleInfo)*HandleBuffer);
}
for(i=0; i<HandleBuffer; i++)
{
HandleInfo *pInfo = (pAllocated+i);
if( 0 == pInfo->handle )
{
pInfo->handle = i+1;
return pInfo;
}
}
return NULL;
}
HandleInfo * GetHandleInfo(Handle h)
{
if( h <= 0 || h >= HandleBuffer-1)
{
return NULL;
}
return (pAllocated+h-1);
}
Handle CreateType(Types typeId)
{
HandleInfo *pInfo;
pInfo = GetFreeHandle();
if( NULL == pInfo )
{
return -1;
}
pInfo->type = typeId;
switch(typeId)
{
case PointType:
pInfo->pData = malloc(sizeof(Point));
ZeroMemory(pInfo->pData, sizeof(Point));
break;
}
return pInfo->handle;
}
int DeleteType(Handle object)
{
HandleInfo *pInfo = GetHandleInfo(object);
if( NULL == pInfo )
{
return -1;
}
if( pInfo->handle != 0 )
{
free(pInfo->pData);
pInfo->pData = NULL;
pInfo->handle = 0;
return 1;
}
else
{
return 0; // Handle was already closed
}
}
void *GetObjectOfCorrectType(Handle object, Types type)
{
HandleInfo *p = GetHandleInfo(object);
if( p == NULL )
{
return NULL;
}
if( p->type != type)
{
return NULL; // handle has wrong object type
}
return p->pData;
}
void IncrementX(Handle point)
{
Point *pPoint = (Point *) GetObjectOfCorrectType(point, PointType);
if( pPoint == NULL )
{
return;
}
pPoint->x++;
}
void PrintPoint(Handle point)
{
Point *pPoint = (Point *) GetObjectOfCorrectType(point, PointType);
if( pPoint == NULL )
{
return;
}
printf("Point has x: %d y: %d", pPoint->x, pPoint->y);
}
Yours,
Alois Kraus
This is the pointer to implementation or pimpl idiom. See http://en.wikibooks.org/wiki/C++_Programming/Idioms#Pointer_To_Implementation_.28pImpl.29 for a tutorial for C++, but the idea should work in C as well.
typedef struct {
/* private members; don't access directly */
void *data;
} point;
You can have separate public header and private header files. Some libraries have conventions for this:
Xt (X11) -> header.h and headerP.h, e.g: X11/Vendor.h vs X11/VendorP.h
Qt -> header.h vs private/header_p.h, e.g: qapplication.h vs private/qapplication_p.h
If you do not want to use the declaration method (because you want the library user to access other members of your struct, for example) it is convention to prepend private member with an underscore, like this:
typedef struct {
void * _data;
} point;
Of course people could still access _data if they would really want to (just like people can access private data in C++ by adding a #define private public before their includes) but that is their own responsibility; at least you have indicated that they shouldn't do that if they want your library to behave as it should.
I use this approach in order to let client alloc the module instance in his STACK.
struct module_private {
int data;
}
typedef uint8_t module_t [sizeof (struct module_private) ];
Client will be able to see private struct content, but not access it without doing a cast that he shouldn't.
Use the following workaround:
#include <stdio.h>
#define C_PRIVATE(T) struct T##private {
#define C_PRIVATE_END } private;
#define C_PRIV(x) ((x).private)
#define C_PRIV_REF(x) (&(x)->private)
struct T {
int a;
C_PRIVATE(T)
int x;
C_PRIVATE_END
};
int main()
{
struct T t;
struct T *tref = &t;
t.a = 1;
C_PRIV(t).x = 2;
printf("t.a = %d\nt.x = %d\n", t.a, C_PRIV(t).x);
tref->a = 3;
C_PRIV_REF(tref)->x = 4;
printf("tref->a = %d\ntref->x = %d\n", tref->a, C_PRIV_REF(tref)->x);
return 0;
}
Result is:
t.a = 1
t.x = 2
tref->a = 3
tref->x = 4

Resources