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.
Related
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 */
}
Can I access pointers from any function without sending info from main() to each function? I've tried looking for information but couldn't find an answer.
Did you try it?
Yes, you can, but using lots of global variables is not a good idea.
If the pointer is passed to the function as parameter or it is declared as global then yes.
Yes you can, because address of variable - it's her own unique identifier in memory space, like a house address within the big city. And e.g. for debug reasons it can be very helpfull (the only thing you should be sure about - live scope of this variable, because when variable leaves her scope - pointer to this address is no longer valid).
As others have said: There are good reasons to not use many globals ("locality of code" is useful), but careful use of globals is justified in some cases. An example might help:
// A slightly contrived example to show how and when you
// might use a global variable in a C program.
#include <stdio.h>
#include <stdlib.h>
// The following are compile-time constants, and considered
// good coding practice
#define DEBUG_WARN 1
#define DEBUG_ERROR 2
// The following is a global, accessible from any function,
// and should be used cautiously. Note the convention (not
// universally adopted) of prefixing its name with "g_"
int g_debug_threshold = 0;
// debug_print() uses the global variable to
// decide whether or not to print a debug message.
void debug_print(char *msg, int level) {
if (level >= g_debug_threshold) {
fprintf(stderr, "%s\n", msg);
}
}
void foo() {
debug_print("hi mom", DEBUG_WARN);
}
int main(int ac, char **av) {
// Here we set the debug threshold at runtime
if (ac > 1) {
g_debug_threshold = atoi(av[1]);
}
foo();
}
Detail of the problem:
Some variables are read from a fixed memory area in RAM into an array. From that array I need to read some variables and use it across the code but these variables need to be constant as they wont be changed in the program any where. Need suggestions to do it effectively! Thanks in advance for any help.
The thought was given for using const variables but then Const variables needs to be initialised during declaration itself. I need to extract bit by bit for each of these variables as I am not able to use memcpy for ensuring portability. Hence I find trouble in declaring the variables as constant.
Put those variables {myVar1, myVar2,...myVarN} into a C file myconsts.c (static to the compilation unit, this will make sure they are not visible outside). Add a header file myconsts.h with function declarations
int getmyVar1(void);
and so on for all the variables and implement the functions in myconsts.c.
They aren't const in the C sense, but they are unwriteable from outside the myconsts.c file. You can initialise them inside myconsts.c, just dont forget to call the init().
If you mean that you are trying to guarantee that these 'constants' end up in flash as opposed to your RAM memory...consult your manual.
You could use inline functions to access the data direct from the array, e.g
static inline myvar() { return array[myvaroffset]; }
Or, if you want the offsets hidden, don't use inline functions and just have a small module that just provides the functions.
If 'myvaroffset' is calculated rather than being a constant and you want to avoid the indexing overhead, copy the array element to a variable during initialisation and return that from the function. If you use real functions, the variables can be static within the function module.
in the function module
/* initialisation */
static int myvarlocal = array[myvaroffset];
...
/* function definitions */
...
int myvar() { return myvarlocal; }
When you want to use it:
i = myvar();
There is probably no need to make things complicated with const pointers etc. Simply use private encapsulation:
// data.h
int data_get (int index);
// data.c
#include "data.h"
static int the_array [N];
int data_get (int index)
{
if(index >= N)
{
// handle errors
}
return array[index];
}
My situation is this:
a header aux_func.h with prototype of a function int check_format_file(FILE * file);
a source file aux_func.c with implementation of that funcion
The question is: In my main.c, where and how is better to declare FILE * f ?
As a static global variable
#include aux_func.h
static FILE * f;
int main()
{
check_format_file(f);
/* other stuffs */
return 0;
}
As an istance variable declare in main ?
#include aux_func.h
int main()
{
FILE * f;
check_format_file(f);
/* other stuffs */
return 0;
}
My doubt is about the correct visibility of FILE *f.
In both the cases, you are passing f to the one and only function check_format_file(), so there is no need to make it static and global. Nobody is going to alter the value of f (I hope so, because if somebody is going to modify it, then you have many more worries than this) and the way you are passing it to the other function, makes sure that it will be visible to the function.
From SO Question,
Variables should always have the smaller scope possible. The argument
behind that is that every time you increase the scope you have more
code that potentially modifies the variable, thus more complexity is
induced in the solution.
It is thus clear that avoiding using global variables is preferred if
the design and implementation naturally allows that. Due to this I
prefer not using global variables unless they are really needed.
I would go with the second option because it seems that you are not going to use the variable f out of this function that's why there is no reason to make it global.
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.