Evaluate a Function Pointer on Structure Member Access in C? - c

I have a problem to solve that would basically just disappear if I could have a member of a struct evaluate to the result of a function when accessed. I don't think I've ever seen any examples of this kind of behavior -- In fact I have a suspicion that what I'm looking for would violate some deep rules of C if not programming in general. If that's the case I'd certainly appreciate hearing it from someone with a little more evidence/experience to explain why.
Here's some simplified code as an example:
/* state.c */
#include "state.h"
state_t state_ctx;
/* state.h */
typedef struct _state_t {
foo_t foo;
}state_t;
extern state_t state_ctx;
#define ACCESS_STATE(x) (state_ctx.x)
/* main.c */
const bar_t bar{
.baz = ACCESS_STATE(foo); // Types are compatible
}
In English there's a global state variable that has a convenient way to redefine access, and that access method is used inside an initializer list for a global variable in the .c file of interest.
That code works, but my mission is to allow to switch contexts from one state variable to another. I can easily change the state definitions to something like:
/* state.c */
#include "state.h"
state_t* p_current_state_ctx; // Now a pointer id's the current state structure
/* state.h */
typedef struct _state_t {
baz_t foo;
}state_t;
extern state_t* p_current_state_ctx;
#define ACCESS_STATE(x) (p_current_state_ctx->x)
All I need to do to switch contexts is set the current state pointer. Nice. But one problem - the initializer lists require the ACCESS_STATE(x) macro to evaluate to a constant. I thought it was brilliant to define a function like:
foo_t func_to_get_foo( void ){
return p_current_state_ctx->foo;
}
So that the main.c initializer could be re-written as:
/* main.c */
const bar_t bar{
.baz = (foo_t)&func_to_get_foo; // Trying to get current state's foo
// Obviously this cast isn't generally correct
// and only compiles if the types are pointers
// but still the behavior is wrong
}
Because the function pointer would be a constant expression. But as I wrote it out my heart deflated because I realized that of course now baz would just be the pointer to func_to_get_foo and not the value of foo like I had fantasized.
The actual program I'm working with is pretty complicated and I'm still learning it's ins and outs. I want to make as few modifications as I can while still getting the multi-state ability. There are a lot of instances of initializer list variables like the bar example so I'd prefer to avoid writing context-switching code for each one.
So if there was some magic that could cause the result of func_to_get_foo() to appear as the result of accessing bar.baz I'd be ecstatic. Does anyone have any advice on how to easily accomplish this?
If there's no way to do that then of course I'd be interested to hear some theory as to why... Or is it cut and dry 'thats just not a feature of C?'
And finally, if there's no clever trick then what is the right way to change these variables that depend on the current state? Will I need to write a function that sets up each and every one every time the context changes?

Assuming I'm following this correctly, bar is a global variable and func_to_get_foo isn't something you can manually fold. That does indeed make it tough. In fact, there's no way to do this in portable c code. In the old days, we put this stuff early in main() which worked well enough.
With gcc we can now use attribute((constructor))
bar_t bar; /* cannot declare this const as this might place it in readonly memory */
attribute((constructor))
static void init_bar(){
bar.baz = func_to_get_foo();
}
Be careful; this only works if state_t state_ctx; was initialized with a const initializer otherwise this technique is utterly unreliable. Attribute initializers do run in an order, but it's not the order you want. In the second case we have to lean even farther on gcc's extensions to replicate c++'s iostream magic as follows:
attribute((constructor))
static void init_bar(){
init_state();
bar.baz = func_to_get_foo();
}
/* ... */
state_t state;
static char state_initialized;
attribute((constructor))
void init_state()
{
if (state_initialized) return;
state_initialized = 1;
/* do whatever to fill out state */
}

Related

Removing (or rather conditionally attach) const modifier using macros in C

I am dealing with the following issue in C. I use global variables for defining some global parameters in my code. I would like such global variables to be constant, even though they have to be initialized inside a routine that reads their values from an input data file. In a nutshell, I am looking for a good way to "cast away" constness during variable initialization in C (I guess in C++ this would not be an issue thanks to const_cast)
I came up with a pattern based on macros to do so, as illustrated below.
It seems to work fine, but I have the following questions.
Does anyone see any hidden flaw or potential danger in the procedure below?
Would anyone discourage the following approach in favor of a simpler one?
My approach:
I have a main header file containing the definition of my global variable (int N) like so
/* main_header.h */
#ifdef global_params_reader
#define __TYPE__QUAL__
#else
#define __TYPE__QUAL__ const
#endif
__TYPE__QUAL__ int N;
I have a file "get_global_params.c" implementing the initialization of N, which sees N as "int N" (as it includes "main_header.h" after defining global_params_reader)
/* get_global_params.c */
#define global_params_reader
#include get_global_params.h
void get_global_params(char* filename){
N = ... ; // calling some function that reads the value of N from
// the datafile "filename" and returns it
}
and the corresponding header file "get_global_params.h"
/* get_global_params.h */
#include "main_header.h"
void get_global_params(char* filename);
Finally, I have a main.c, which sees N as "const int N" (as it includes "main_header.h" without defining global_params_reader):
/* main.c */
#include "main_header.h"
#include "get_global_params.h"
int main(int argc, char **argv){
// setting up input data file //
...
// initialize N //
get_global_params(datafile);
// do things with N //
...
}
I hope my explanation was clear enough.
Thanks for any feedback.
Just contain the globals in a separate file.
globl.h:
struct Globals{
int N;
//...
};
extern const struct Globals *const globals;
init_globl.h:
init_globals(/*Init Params*/);
globl.c
#include globl.h
#include init_globl.h
static struct Globals _globals;
const struct Globals *const globals = &_globals;
init_globals(/*Init Params*/){
// Initialize _globals;
//...
}
Now you can initialize the globals at startup by including init_globl.h in whatever file needs access to that functionality, everyone else can directly access the globals just by including globl.h, and using the notation globals->N.
If I were you, I would simply avoid this kind of global variables. Instead, I would define a struct with all those program parameters, and define one function that returns a const pointer to the one and only instance of this struct (singleton pattern). That way, the function that returns the pointer has non-const access to the singleton, while the entire rest of the program does not. This is precisely what you need, it's clean and object oriented, so there is no reason to mess around with macros and casts.
The instance can be declared as a static variable within the function or it can be malloc'ed to a static pointer. It does not really matter, because that is an implementation detail of that function which is never leaked to the outside. Nor does the rest of the code need to be aware of when the parameters are actually read, it just calls the function and it gets the one and only object with all valid parameters.
"I would like such global variables to be constant, even though they have to be initialized inside a routine that reads their values from an input data file."
It is not possible to initialize a const in c during run-time. In c value either has or has not a const qualifier, and it is defined upon declaration. c does not support changing it. The semantics are fixed. But some expert with quoting the standard would be nicer and more ensuring.
I don't think this is possible in c++ either, but I won't bet on it, since c++ can do some magic here and there.

Regarding typedefs of 1-element arrays in C

Sometimes, in C, you do this:
typedef struct foo {
unsigned int some_data;
} foo; /* btw, foo_t is discouraged */
To use this new type in an OO-sort-of-way, you might have alloc/free pairs like these:
foo *foo_alloc(/* various "constructor" params */);
void foo_free(foo *bar);
Or, alternatively init/clear pairs (perhaps returning error-codes):
int foo_init(foo *bar, /* and various "constructor" params */);
int foo_clear(foo *bar);
I have seen the following idiom used, in particular in the MPFR library:
struct foo {
unsigned int some_data;
};
typedef struct foo foo[1]; /* <- notice, 1-element array */
typedef struct foo *foo_ptr; /* let's create a ptr-type */
The alloc/free and init/clear pairs now read:
foo_ptr foo_alloc(/* various "constructor" params */);
void foo_free(foo_ptr bar);
int foo_init(foo_ptr bar, /* and various "constructor" params */);
int foo_clear(foo_ptr bar);
Now you can use it all like this (for instance, the init/clear pairs):
int main()
{
foo bar; /* constructed but NOT initialized yet */
foo_init(bar); /* initialize bar object, alloc stuff on heap, etc. */
/* use bar */
foo_clear(bar); /* clear bar object, free stuff on heap, etc. */
}
Remarks: The init/clear pair seems to allow for a more generic way of initializing and clearing out objects. Compared to the alloc/free pair, the init/clear pair requires that a "shallow" object has already been constructed. The "deep" construction is done using init.
Question: Are there any non-obvious pitfalls of the 1-element array "type-idiom"?
This is very clever (but see below).
It encourages the misleading idea that C function arguments can be passed by reference.
If I see this in a C program:
foo bar;
foo_init(bar);
I know that the call to foo_init does not modify the value of bar. I also know that the code passes the value of bar to a function when it hasn't initialized it, which is very probably undefined behavior.
Unless I happen to know that foo is a typedef for an array type. Then I suddenly realize that foo_init(bar) is not passing the value of bar, but the address of its first element. And now every time I see something that refers to type foo, or to an object of type foo, I have to think about how foo was defined as a typedef for a single-element array before I can understand the code.
It is an attempt to make C look like something it's not, not unlike things like:
#define BEGIN {
#define END }
and so forth. And it doesn't result in code that's easier to understand because it uses features that C doesn't support directly. It results in code that's harder to understand (especially to readers who know C well), because you have to understand both the customized declarations and the underlying C semantics that make the whole thing work.
If you want to pass pointers around, just pass pointers around, and do it explicitly. See, for example, the use of FILE* in the various standard functions defined in <stdio.h>. There is no attempt to hide pointers behind macros or typedefs, and C programmers have been using that interface for decades.
If you want to write code that looks like it's passing arguments by reference, define some function-like macros, and give them all-caps names so knowledgeable readers will know that something odd is going on.
I said above that this is "clever". I'm reminded of something I did when I was first learning the C language:
#define EVER ;;
which let me write an infinite loop as:
for (EVER) {
/* ... */
}
At the time, I thought it was clever.
I still think it's clever. I just no longer think that's a good thing.
The only advantage to this method is nicer looking code and easier typing. It allows the user to create the struct on the stack without dynamic allocation like so:
foo bar;
However, the structure can still be passed to functions that require a pointer type, without requiring the user to convert to a pointer with &bar every time.
foo_init(bar);
Without the 1 element array, it would require either an alloc function as you mentioned, or constant & usage.
foo_init(&bar);
The only pitfall I can think of is the normal concerns associated with direct stack allocation. If this in a library used by other code, updates to the struct may break client code in the future, which would not happen when using an alloc free pair.

"Private" struct members in C with const

In order to have a clean code, using some OO concept can be useful, even in C.
I often write modules made of a pair of .h and .c files. The problem is that the user of the module have to be careful, since private members don't exist in C. The use of the pimpl idiom or abstract data types is ok, but it adds some code and/or files, and requires a heavier code. I hate using accessor when I don't need one.
Here is a idea which provides a way to make the compiler complain about invalid access to "private" members, with only a few extra code. The idea is to define twice the same structure, but with some extra 'const' added for the user of the module.
Of course, writing in "private" members is still possible with a cast. But the point is only to avoid mistakes from the user of the module, not to safely protect memory.
/*** 2DPoint.h module interface ***/
#ifndef H_2D_POINT
#define H_2D_POINT
/* 2D_POINT_IMPL need to be defined in implementation files before #include */
#ifdef 2D_POINT_IMPL
#define _cst_
#else
#define _cst_ const
#endif
typedef struct 2DPoint
{
/* public members: read and write for user */
int x;
/* private members: read only for user */
_cst_ int y;
} 2DPoint;
2DPoint *new_2dPoint(void);
void delete_2dPoint(2DPoint **pt);
void set_y(2DPoint *pt, int newVal);
/*** 2dPoint.c module implementation ***/
#define 2D_POINT_IMPL
#include "2dPoint.h"
#include <stdlib.h>
#include <string.h>
2DPoint *new_2dPoint(void)
{
2DPoint *pt = malloc(sizeof(2DPoint));
pt->x = 42;
pt->y = 666;
return pt;
}
void delete_2dPoint(2DPoint **pt)
{
free(*pt);
*pt = NULL;
}
void set_y(2DPoint *pt, int newVal)
{
pt->y = newVal;
}
#endif /* H_2D_POINT */
/*** main.c user's file ***/
#include "2dPoint.h"
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
2DPoint *pt = new_2dPoint();
pt->x = 10; /* ok */
pt->y = 20; /* Invalid access, y is "private" */
set_y(pt, 30); /* accessor needed */
printf("pt.x = %d, pt.y = %d\n", pt->x, pt->y); /* no accessor needed for reading "private" members */
delete_2dPoint(&pt);
return EXIT_SUCCESS;
}
And now, here is the question: is this trick OK with the C standard?
It works fine with GCC, and the compiler doesn't complain about anything, even with some strict flags, but how can I be sure that this is really OK?
This is almost certainly undefined behavior.
Writing/modifying an object declared as const is prohibited and doing so results in UB. Furthermore, the approach you take re-declares struct 2DPoint as two technically different types, which is also not permitted.
Note that this (as undefined behavior in general) does not mean that it "certainly won't work" or "it must crash". In fact, I find it quite logical that it works, because if one reads the source intelligently, he may easily find out what the purpose of it is and why it migh be regarded as correct. However, the compiler is not intelligent - at best, it's a finite automaton which has no knowledge about what the code is supposed to do; it only obeys (more or less) to the syntactical and semantical rules of the grammar.
This violates C 2011 6.2.7 1.
6.2.7 1 requires that two definitions of the same structure in different translation units have compatible type. It is not permitted to have const in one and not the other.
In one module, you may have a reference to one of these objects, and the members appear to be const to the compiler. When the compiler writes calls to functions in other modules, it may hold values from the const members in registers or other cache or in partially or fully evaluated expressions from later in the source code than the function call. Then, when the function modifies the member and returns, the original module will not have the changed value. Worse, it may use some combination of the changed value and the old value.
This is highly improper programming.
In Bjarne Stroustrup's words: C is not designed to support OOP, although it enables OOP, which means it is possible to write OOP programs in C, but only very hard to do so. As such, if you have to write OOP code in C, there seems nothing wrong with using this approach, but it is preferable to use a language better suited for the purpose.
By trying to write OOP code in C, you have already entered a territory where "common sense" has to be overridden, so this approach is fine as long as you take responsibility to use it properly. You also need to ensure that it is thoroughly and rigourously documented and everyone concerned with the code is aware of it.
Edit Oh, you may have to use a cast to get around the const. I fail to recall if the C-style cast can be used like C++ const_cast.
You can use different approach - declare two structs, one for user without private members (in header) and one with private members for internal use in your implementation unit. All private members should be placed after public ones.
You always pass around the pointer to the struct and cast it to internal-use when needed, like this:
/* user code */
struct foo {
int public;
};
int bar(void) {
struct foo *foo = new_foo();
foo->public = 10;
}
/* implementation */
struct foo_internal {
int public;
int private;
};
struct foo *new_foo(void) {
struct foo_internal *foo == malloc(sizeof(*foo));
foo->public = 1;
foo->private = 2;
return (struct foo*)foo; // to suppress warning
}
C11 allows unnamed structure fields (GCC supports it some time), so in case of using GCC (or C11 compliant compiler) you can declare internal structure as:
struct foo_internal {
struct foo;
int private;
};
therefore no extra effort required to keep structure definitions in sync.

Is this an appropriate use of void pointers?

This question is about the appropriateness of using void pointers in a particular implementation.
I have a relatively simple program that consists of an infinite loop. On each loop, the program iterates over a fixed range of constant values and calls a function on each value. The particular function which is called can be one of three available and is specified at run time by an argument. Before the infinite loop starts, there is a condition block which sets a functional pointer to a function based on the supplied argument. This way the condition logic only has to be run once and not on every iteration in every loop.
This I have implemented and it works well, but I want to keep state between each call to the function. My proposal is to store state in a struct and pass that struct when calling the function on each of the values. The problem is that each function requires a different struct to store a different set of values of its state and the prototype of all three functions must be compatible (for the function pointer). I intend to solve this by using a void pointer in the prototypes of the three functions, thus maintaining compatible prototypes but allowing me to pass a different struct to each function.
The question is; is my proposal an appropriate use of void pointers or is it introducing too much runtime dynamism and I should therefore rethink my approach?
Note: It is not possible to use static variables in each of the three functions as the structs also need to be available in the infinite loop as there is also some processing to be done before and after the range of values is iterated.
As long as you are careful to keep your calls type-correct, this is a fairly C-idiomatic way to accomplish what you describe.
You could gain some measure of type safety by using a union:
typedef struct {
int a;
char *b;
} s1;
typedef struct {
double d;
int *e;
} s2;
typedef union {
s1 s1;
s2 s2;
} ocd;
typedef int (*daemon_function)(ocd *);
Then all your functions could be of type daemon_function but take different arguments through ocd.s1 or ocd2.s2. I'd tend to call all that a bunch of pointless busy-work though. A simple void* would work just as well.
You could also include a magic number at the front of your structures and then the functions could check type safety by looking at the magic number and seeing if it was the right one:
#define MAGIC 0x4d475600L
typedef struct {
long magic;
/* ... */
} whatever;
And then:
int f(void *p) {
whatever *w = (whatever *)p;
if(w->magic != MAGIC) {
/* complain and go boom! */
}
/* ... */
}
I did the magic number trick all the time back in my Motif programming days, you pass around a lot of void* pointers in Motif/Xt/X11 development.
Void pointers are a method to tell the c typing system that you want it to stop doing its job and trust you to not mess up. It is an appropriate use of a void *, the only issue is that you have lost access to any type checking that your compiler performs. You can potentially create some very bizarre and hard to diagnose bugs. If you are sure that you know what you are doing (you sound like you do) and if you have checked every single line of your code several times and are sure that there are no logical errors in it, then you should be fine.
void * is quite idiomatic in C. Personally I use it prevalently, but whenever I do it, I tend to used tagged structures for safety, i.e. I put a unique type ID at the beginning of each structure to identify it.
Generally it is OK.
I really prefer using the void * contexts but it looks like you want to avoid it.
Since you already have some code that parses the argument and choose the function, you can just select the function in a switch and call it explicitly for each iteration.

Portable way to "unpoint" a pointer typedef?

This is unfortunately defined in some external library: cannot touch!
// library.h
typedef struct {
long foo;
char *bar;
/* ... (long & complex stuff omitted) */
} *pointer_to_complex_struct_t;
Now The Question: how to declare an complex_struct_t variable?
Ideal solution but not allowed! (cannot change external library):
// library.h
/* ... (long & complex stuff omitted) */
} complex_struct_t, *pointer_to_complex_struct_t;
// my.h
extern complex_struct_t my_variable;
Non-portable solution (gcc):
// my.h
extern typeof( * (type_placeholder)0 ) my_variable; // Thanks caf!
Other? Better? Thanks!
Bonus question: same question for a function pointer (in case there is any difference; I doubt it).
ADDED bonus: below is the exact same question but with functions instead of structs. This should not make any difference to the short answer ("No."), the only answer I was initially interested in. I did not expect some people to die trying to know and get my job done with creative workarounds, which is why I simplified the question from functions to structs (function pointers have special implicit conversion rules for convenience and confusion). But hey, why not? Let's get the copy-paste workaround competition started. Some workarounds are probably better than others.
///// library.h //////
// Signature has been simplified
typedef double (*ptr_to_callback_t)(long, int, char *);
// Too bad this is not provided: typedef double callback_t(long, int, char *);
///// my.h /////
// This avoids copy-paste but is not portable
typedef typeof( * (ptr_to_callback_t)0 ) callback_t;
extern callback_t callback_1;
extern callback_t callback_2;
extern callback_t callback_3;
// etc.
Short answer = no, there is currently no portable alternative to typeof
A basic copy-paste workaround works OK for functions but not for structs. The compiler will match the duplicated function types, but will not relate the duplicated struct types: a cast is required and the duplicated struct types will diverge without compilation warning.
No, unfortunately you cannot do it with standard C. With C++ a simple metafunction would do the trick though.
However you could just copy-paste the definition of the struct thus leaving the original untouched
typedef struct {
///same struct
} complex_struct_t;
The downside of this solution is that the expression &complex_struct_t won't be of type pointer_to_complex_struct_t, instead it will be of type pointer to unnamed struct {//your members};
You'll need reinterpret_casting, if you need that feature...
As written, the answer to your question is "no"; if all you have is a type definition of
typedef struct {...} *ptr_to_struct;
then there's no (standard, portable) way to extract the struct type. If you have to create an instance of the struct, the best you will be able to do is
ptr_to_struct s = malloc(sizeof *s);
and then refer to the fields in the struct using the -> component selection operator (or by dereferencing s and using the . operator, but you don't want to do that).
You asked if the same thing applied to function pointers; you really need to state exactly what you mean. If you have a situation like
typedef struct {...} *ptr_to_struct;
ptr_to_struct foo() {...}
then the situation is exactly like the above; you don't have a way to declare a variable of that type.
Make a local copy of the header file and include it instead of the original. Now you can do anything you want. If this library could change (update or anything else), you could write a little script to automate these steps and call it from your makefile whenever you compile. Just make sure to not blindly paste into the header, search for the specific line (} *pointer_to_complex_struct_t;) and throw an error if it is no longer found.
Maybe you have to be a bit careful with the search paths for includes if this header uses other headers of this library. Plus, with the order of includes if itself is included by other headers.
EDIT (for your real goal mentioned in a comment): You can't do this with function pointers. Just write the function you want with the signature of the typedef, and it will be compatible to the pointer and can be called by it.
How about:
pointer_to_complex_struct_t newStruct ( void ) {
pointer_to_complex_struct_t ptr =
(pointer_to_complex_struct_t) malloc ( sizeof (*pointer_to_complex_struct_t) );
return ptr;
}
You'd have to reference your newly created struct through ptr-> but you could create new ones.
Of course, this may or may not work, depending on how the struct is actually used. The example that comes to mind is: what if the struct ends with
char data[0];
and data is used to point into the memory following the structure.

Resources