How, exactly, to use file-wide static variables in C? - c

I'm going round and round in circles trying to work out how to implement variables that need to be accessed by multiple functions within a [.c] file.
I have been ploughing through thread after thread on Stack Exchange and other Google searches where the general [but certainly not unanimous] consensus seems to be that file-wide static variables are fine, yet, you should pass variables (or at the very least pointers to variables) into functions and not just have any old function access the static file-wide variable (i.e. one that is declared outside of any function). Some people have said file-wide statics are essentially as bad as globals, but give no indication of how to avoid globals if not with file-wide statics!
However, at some point, even if you pass pointers to the file-wide static variable from function to function, some function has to originally access that file-wide static variable. Also, I cannot see a way where just one function within the .c file can be the sole function that accesses that static variable, because not all functions that will need the static variable would go through one single function.
It seems to me that you could have a function that does nothing but holds a static variable and returns a pointer to that static variable. Any function that needs to access that variable calls that function, gets the pointer to the variable and does what it needs to do with the variable. This kind of thing:
struct PacketStruct* GetPacketStructPtr(void)
{
static struct PacketStruct Packet;
return &Packet;
}
I've seen some people here say, yep, that's how a singleton factory is built (whatever that is) and it's completely valid, yet others say it's dangerous (but without really explaining why it's dangerous), others have said it's poor practice (I think they said it was inefficient, but I've read so much today I could be wrong).
So, what I am trying to ascertain is this:
Are file wide variables OK?
If so, given that it seems so wrong just to have all functions access that file-wide static variable and not pass pointers to it [the static file-wide variable] - as much as anything to make function re-use with different variables possible - can you just decide the first function that needs to access the file-wide static does so and then passes pointers all the way down to other functions? I really hate the look of code that just access the file-wide static variable, even though it also seems a little daft passing a pointer to something that the function can access anyway.
If file-wide static variables are not valid, given that this is not multi-threaded and just a run-to-complete program on an embedded micro, can/should I use that way of passing a pointer to the function-wide static variable to any other function that needs access to the variable?
If none of the above, how on earth do you avoid the dreaded global variables? This question of not using globals seems to have been tackled a zillion times here but without any concrete examples of how to do it. There is an awful lot of contradictory advice knocking about here, let alone on the rest of the web!
I stress this is single thread, not re-entrant and all relatively simple.
Hopefully, this gives some more idea about what I'm trying to do:
#include "work_order.h
// This is work_order.c
// Nothing outside of this file needs to access the WorkOrder struct
static struct WorkOrderStruct WorkOrder;
// Package up a work order - *data is a pointer to a complete serial package
int16_t CableConnectOrder(uint8_t *Data)
{
if (UnpackagePortInformation(&WorkOrder.PortA,&Data) == CARD_UID_NOT_FOUND)
return CARD_UID_NOT_FOUND;
if (UnpackagePortInformation(&WorkOrder.PortB,&Data) == CARD_UID_NOT_FOUND)
return CARD_UID_NOT_FOUND;
AddNewKeysToWorkOrder(&WorkOrder,Data);
WorkOrder.WorkOrderType = CONNECT_CABLE_REQUEST;
WorkOrder.Flags.SingleEndedConnection = FALSE_BIT;
WorkOrder.Flags.PortACableRemoveRequest = FALSE;
WorkOrder.Flags.PortBCableRemoveRequest = FALSE;
return ConstructCableOrderRequest(&WorkOrder);
}
int16_t ConstructCableOrderRequest(struct WorkOrderStruct *WorkOrder)
{
// This function is accessed by other Work Order requests and does the rest of the // packaging of the work order
// It can also pass the work order information further down
DoOtherStuff(WorkOrder); // Kind of further passing that might happen
}
int16_t CheckAdditionalInfoAgainstWorkOrder(struct WorkOrderPortUpdateStruct *Update)
{
// Compare connection information against the previously set-up work order
// Needs to access the static WorkOrder structure as well. Also, can call other
// functions that needs to access the static function
WorkOrder.Foo = Update->bar;
DoYetMoreOtherStuff(&WorkOrder); // This is not real code, but the general kind of idea
}

More information on what you're doing would be helpful. I often do embedded system programming where globals/file-wide statics are an absolute must due to interrupts. If that is what you're working on - go for it.
Re: A single function that creates the variable and passes a pointer to all other functions...
Your "single function" would be main. I'll often create code like so...
struct PacketStruct {
char name[128];
uint8_t age;
float bac;
}
void setup (PacketStruct *packetStruct, ...);
void foo (PacketStruct *parameter);
void bar (PacketStruct *parameter);
int main (void) {
PacketStruct ps;
// Initialize all variables"
setup(&ps);
// Run program
foo(&ps);
bar(&ps);
return 0;
}
void setup (PacketStruct *packetStruct, ...) {
strcpy(packetStruct->name, "Squidward");
packetStruct->age = 16;
packetStruct->bac = 0.11;
}
I like this because ps is not a global variable, you do not have to dynamically allocate memory (though you could just as easily do so), and it becomes accessible in all functions.
Again, if you post your full code (or a snippet showing how it's used) we might be able to give you some applications specific advice.
-Edit-
Since you're mentioning file-wide, I'm guessing that means you're not using this variable in the same file as main. In that case, my sub-files will have functions like filename_init(...)...
/* File: FooBar.c
*/
#include "FileWithPacketStructAndOtherCoolThings.h"
// "g_" sits in front of all global variables
// "FooBar_" sits in front of all file-wide statics
static PacketStruct g_FooBar_ps;
FooBar_init(void) {
strcpy(g_ps->name, "Squidward");
g_ps->age = 16;
g_ps->bac = 0.11;
}

Related

Accessing global structs in C functions

My understanding is that C functions only work with copies of variables unless passed by address. However, the following appears to work OK, and I am confused as to why. I am accessing a global struct in a function and it appears to change the global value even though I am not passing the address.
Global struct:
cal{
int a;
int b;
}cal;
Function:
AlterCalAandCalB()
{
cal.a = 1;
cal.b = 2;
}
This appears to change the global variable not just inside function.
I rewrote the code to this, and the performance is identical:
AlterCalAandCalB(struct cal *ptrCal)
{
ptrCal->a = 1;
ptrCal->b = 2;
}
I am interested in learning the best practice, not just what works. I realize that global variables are not recommended but in this particular case it works for me. But I want to learn the best practice for pointers.
My understanding is that C functions only work with copies of variables unless passed by address.
That's slightly confused. C functions receive their arguments by value -- roughly speaking, they receive copies, including if the argument is the address of an object or function. This is about argument passing, not about the behavior of the statements in function bodies.
Every executable statement is inside a function body. There would be no point to "global" variables if functions could not share access to them.
I am interested in learning the best practice, not just what works.
Best practice is a matter of opinion, so it is off topic here. But note that if you are going to pass the address of an object to all functions that you want to access it (excluding main(), I suppose), then there is no point to declaring that object at file scope in the first place.

c accessing data members in different translation unit

I wrote some code that uses function pointers to link modules functions in c. I was wondering is it possible to use those function pointers to access state in another translation unit.
I wrote this struct to handle life cycle functions so that I can have a module doing everything, you pass in a pointer to this struct with your functions and they get called when they are suppose to.
typedef struct {
void (*init_func_ptr)(void);
void (*fixed_update_func_ptr)(void);
void (*variable_update_func_ptr)(double alpha);
void (*variable_render_func_ptr)(double alpha);
void (*pause_func_ptr)(void);
void (*resume_func_ptr)(void);
void (*resize_func_ptr)(int width, int height);
void (*handle_event_func_ptr)(key_event *e);
void (*quit_func_ptr)(void);
} lifecycle_ptrs;
i typically set it up like this
lifecycle_ptrs* ptrs;
ptrs = calloc(1, sizeof(lifecycle_ptrs));
ptrs->init_func_ptr = &init;
ptrs->fixed_update_func_ptr = &fixed_update;
ptrs->variable_update_func_ptr = &variable_update;
ptrs->variable_render_func_ptr = &variable_render;
ptrs->pause_func_ptr = &pause;
ptrs->resume_func_ptr = &resume;
ptrs->resize_func_ptr = &resize;
ptrs->handle_event_func_ptr = &handle_events;
ptrs->quit_func_ptr = &quit;
this ptrs struct is setup in the module that defines main and is passed as a function argument. Once this is passed the program goes into an infinite loop until the user requests to quit.
So far this works pretty well and does what I want to do.
What I was curious about now is, is it possible to have something like this where I am able to access variables from the other module?
Let's say module a looks like this
modulea.c
int a;
int b;
char t[] = "test";
moudleb.c
struct t;
float 12.0;
is it possible to access module a's member variables from moduleb or visa versa?
I could write functions to get each thing but I feel there might be more elegant and maintainable way to do that. I could also define a struct and do a swap function where module a get access to the variables in module b and visa versa but again this seems a bit odd to me.
Are there any other ways to do this? I am more concerned about maintainability but any insights would help because right now I am at a loss.
Yes, technically it is possible, simply use extern.
However, there is no reason why you should ever do that. If you ever come up with a need to access (non-constant) variables in another file, then that means that your program design is broken.
And if you go through with extern, it will become even more broken, you'll get complete spaghetti code with very tight coupling, where everything in the program depends on everything else and all bugs will fail-escalate through the program and tear down things completely unrelated to the bug.
So the proper solution is to step back and think twice about the overall program design.
Instead of such spaghetti-coding, use object-oriented design and write each h and c file pair so that they together form an autonomous module (call it class, ADT or what you will), which is only concerned with it's own designated purpose. All file scope variables inside such a c file should be declared static to block access from outside. Access to such variables, if at all needed, should be done through setter/getter functions. The only kind of variables that is acceptable to share directly across files are read-only constants.
Though note that you should avoid file scope variables as far as possible, as they will make the code non-reentrant.
Easiest way to share members between different c modules is to use headers files.
You could add a modulea.h file to your project like:
#ifndef modulea_H_
#define modulea_H_
extern int a;
extern int b;
extern char t[];
#endif
Then you can #include "modulea.h" in your moduleb.c source file.

Making C module variables accessible as read-only

I would like to give a module variable a read-only access for client modules.
Several solutions:
1. The most common one:
// module_a.c
static int a;
int get_a(void)
{
return a;
}
// module_a.h
int get_a(void);
This makes one function per variable to share, one function call (I am thinking both execution time and readability), and one copy for every read. Assuming no optimizing linker.
2. Another solution:
// module_a.c
static int _a;
const int * const a = &_a;
// module_a.h
extern const int * const a;
// client_module.c
int read_variable = *a;
*a = 5; // error: variable is read-only
I like that, besides the fact that the client needs to read the content of a pointer. Also, every read-only variable needs its extern const pointer to const.
3. A third solution, inspired by the second one, is to hide the variables behind a struct and an extern pointer to struct. The notation module_name->a is more readable in the client module, in my opinion.
4. I could create an inline definition for the get_a(void) function. It would still look like a function call in the client module, but the optimization should take place.
My questions:
Is there a best way to make variables modified in a module accessible as read-only in other modules? Best in what aspect?
Which solutions above would you accept or refuse to use, and why?
I am aware that this is microoptimization - I might not implement it - but I am still interested in the possibility, and above all in the knowing.
Concerning option #4, I'm not sure you can make it inline if the variable isn't accessible outside the implementation file. I wouldn't count options #2 and #3 as truly read-only. The pointer can have the constness cast away and be modified (const is just a compiler "warning", nothing concrete). Only option #1 is read-only because it returns a copy.
For speed identical to variable access, you can define an extern variable inside an inline function:
static inline int get_a(void)
{
extern int a_var;
return a_var;
}
This is simple and clear to read. The other options seem unnecessarily convoluted.
Edit: I'm assuming that you use prefixes for your names, since you write C. So it will actually be:
extern int my_project_a;
This prevents a client from accidentally making a variable with the same name. However, what if a client makes a variable with the same name on purpose? In this situation, you have already lost, because the client is either 1) actively trying to sabotage your library or 2) incompetent beyond reasonable accommodation. In situation #1, there is nothing you can do to stop the programmer. In situation #2, the program will be broken anyway.
Try running nm /lib/libc.so or equivalent on your system. You'll see that most libc implementations have several variables that are not defined in header files. On my system this includes things like __host_byaddr_cache. It's not the responsibility of the C library implementors to babysit me and prevent me from running:
extern void *__host_byaddr_cache;
__host_byaddr_cache = NULL;
If you start down the path of thinking that you have to force clients to treat your variable as read-only, you are heading down the path of fruitless paranoia. The static keyword is really just a convenience to keep objects out of the global namespace, it is not and never was a security measure to prevent external access.
The only way to enforce read-only variables is to manage the client code — either by sandboxing it in a VM or by algorithmically verifying that it can't modify your variable.
The most common one:
There's a reason why it's the most common one. It's the best one.
I don't regard the performance hit to be significant enough to be worth worrying about in most situations.

Internal static variables in C, would you use them?

In C you can have external static variables that are viewable every where in the file, while internal static variables are only visible in the function but is persistent
For example:
#include <stdio.h>
void foo_bar( void )
{
static counter = 0;
printf("counter is %d\n", counter);
counter++;
}
int main( void )
{
foo_bar();
foo_bar();
foo_bar();
return 0;
}
the output will be
counter is 0
counter is 1
counter is 2
My question is why would you use an internal static variable? If you don't want your static variable visible in the rest of the file shouldn't the function really be in its own file then?
This confusion usually comes about because the static keyword serves two purposes.
When used at file level, it controls the visibility of its object outside the compilation unit, not the duration of the object (visibility and duration are layman's terms I use during educational sessions, the ISO standard uses different terms which you may want to learn eventually, but I've found they confuse most beginning students).
Objects created at file level already have their duration decided by virtue of the fact that they're at file level. The static keyword then just makes them invisible to the linker.
When used inside functions, it controls duration, not visibility. Visibility is already decided since it's inside the function - it can't be seen outside the function. The static keyword in this case, causes the object to be created at the same time as file level objects.
Note that, technically, a function level static may not necessarily come into existence until the function is first called (and that may make sense for C++ with its constructors) but every C implementation I've ever used creates its function level statics at the same time as file level objects.
Also, whilst I'm using the word "object", I don't mean it in the sense of C++ objects (since this is a C question). It's just because static can apply to variables or functions at file level and I need an all-encompassing word to describe that.
Function level statics are still used quite a bit - they can cause trouble in multi-threaded programs if that's not catered for but, provided you know what you're doing (or you're not threading), they're the best way to preserve state across multiple function calls while still providing for encapsulation.
Even with threading, there are tricks you can do in the function (such as allocation of thread specific data within the function) to make it workable without exposing the function internals unnecessarily.
The only other choices I can think of are global variables and passing a "state variable" to the function each time.
In both these cases, you expose the inner workings of the function to its clients and make the function dependent on the good behavior of the client (always a risky assumption).
They are used to implement tools like strtok, and they cause problems with reentrancy...
Think carefully before fooling around with this tool, but there are times when they are appropriate.
For example, in C++, it is used as one way to get singleton istances
SingletonObject& getInstance()
{
static SingletonObject o;
return o;
}
which is used to solve the initialization order problem (although it's not thread-safe).
Ad "shouldn't the function be in its own file"
Certainly not, that's nonsense. Much of the point of programming languages is to facilitate isolation and therefore reuse of code (local variables, procedures, structures etc. all do that) and this is just another way to do that.
BTW, as others pointed out, almost every argument against global variables applies to static variables too, because they are in fact globals. But there are many cases when it's ok to use globals, and people do.
I find it handy for one-time, delayed, initialization:
int GetMagic()
{
static int magicV= -1;
if(-1 == magicV)
{
//do expensive, one-time initialization
magicV = {something here}
}
return magicV;
}
As others have said, this isn't thread-safe during it's very first invocation, but sometimes you can get away with it :)
I think that people generally stay away from internal static variables. I know strtok() uses one, or something like it, and because of that is probably the most hated function in the C library.
Other languages like C# don't even support it. I think the idea used to be that it was there to provide some semblance of encapsulation (if you can call it that) before the time of OO languages.
Probably not terribly useful in C, but they are used in C++ to guarantee the initialisation of namespace scoped statics. In both C and C++ there are problemns with their use in multi-threaded applications.
I wouldn't want the existence of a static variable to force me to put the function into its own file. What if I have a number of similar functions, each with their own static counter, that I wanted to put into one file? There are enough decisions we have to make about where to put things, without needing one more constraint.
Some use cases for static variables:
you can use it for counters and you won't pollute the global namespace.
you can protect variables using a function that gets the value as a pointer and returns the internal static. This whay you can control how the value is assigned. (use NULL when you just want to get the value)
I've never heard this specific construct termed "internal static variable." A fitting label, I suppose.
Like any construct, it has to be used knowledgeably and responsibly. You must know the ramifications of using the construct.
It keeps the variable declared at the most local scope without having to create a separate file for the function. It also prevents global variable declaration.
For example -
char *GetTempFileName()
{
static int i;
char *fileName = new char[1024];
memset(fileName, 0x00, sizeof(char) * 1024);
sprintf(fileName, "Temp%.05d.tmp\n", ++i);
return fileName;
}
VB.NET supports the same construct.
Public Function GetTempFileName() As String
Static i As Integer = 0
i += 1
Return String.Format("Temp{0}", i.ToString("00000"))
End Function
One ramification of this is that these functions are not reentrant nor thread safe.
Not anymore. I've seen or heard the results of function local static variables in multithreaded land, and it isn't pretty.
In writing code for a microcontroller I would use a local static variable to hold the value of a sub-state for a particular function. For instance if I had an I2C handler that was called every time main() ran then it would have its own internal state held in a static local variable. Then every time it was called it would check what state it was in and process I/O accordingly (push bits onto output pins, pull up a line, etc).
All statics are persistent and unprotected from simultaneous access, much like globals, and for that reason must be used with caution and prudence. However, there are certainly times when they come in handy, and they don't necessarily merit being in their own file.
I've used one in a fatal error logging function that gets patched to my target's error interrupt vectors, eg. div-by-zero. When this function gets called, interrupts are disabled, so threading is a non-issue. But re-entrancy could still happen if I caused a new error while in the process of logging the first error, like if the error string formatter broke. In that case, I'd have to take more drastic action.
void errorLog(...)
{
static int reentrant = 0;
if(reentrant)
{
// We somehow caused an error while logging a previous error.
// Bail out immediately!
hardwareReset();
}
// Leave ourselves a breadcrumb so we know we're already logging.
reentrant = 1;
// Format the error and put it in the log.
....
// Error successfully logged, time to reset.
hardwareReset();
}
This approach is checking against a very unlikely event, and it's only safe because interrupts are disabled. However, on an embedded target, the rule is "never hang." This approach guarantees (within reason) that the hardware eventually gets reset, one way or the other.
A simple use for this is that a function can know how many times it has been called.

Refactoring global to local. Should they be static or not?

I'm refactoring "spaghetti code" C module to work in multitasking (RTOS) environment.
Now, there are very long functions and many unnecessary global variables.
When I try to replace global variables that exists only in one function with locals, I get into dilemma. Every global variable is behave like local "static" - e.g. keep its value even you exit and re-enter to the function.
For multitasking "static" local vars are worst from global. They make the functions non reentered.
There are a way to examine if the function is relay on preserving variable value re-entrancing without tracing all the logical flow?
Short answer: no, there isn't any way to tell automatically whether the function will behave differently according to whether the declaration of a local variable is static or not. You just have to examine the logic of each function that uses globals in the original code.
However, if replacing a global variable with a static local-scope variable means the function is not re-entrant, then it wasn't re-entrant when it was a global, either. So I don't think that changing a global to a static local-scope variable will make your functions any less re-entrant than they were to start with.
Provided that the global really was used only in that scope (which the compiler/linker should confirm when you remove the global), the behaviour should be close to the same. There may or may not be issues over when things are initialized, I can't remember what the standard says: if static initialization occurs in C the same time it does in C++, when execution first reaches the declaration, then you might have changed a concurrency-safe function into a non-concurrency-safe one.
Working out whether a function is safe for re-entrancy also requires looking at the logic. Unless the standard says otherwise (I haven't checked), a function isn't automatically non-re-entrant just because it declares a static variable. But if it uses either a global or a static in any significant way, you can assume that it's non-re-entrant. If there isn't synchronization then assume it's also non-concurrency-safe.
Finally, good luck. Sounds like this code is a long way from where you want it to be...
If your compiler will warn you if a variable is used before initialized, make a suspected variable local without assigning it a value in its declaration.
Any variable that gives a warning cannot be made local without changing other code.
Changing global variables to static local variables will help a little, since the scope for modification has been reduced. However the concurrency issue still remains a problem and you have to work around it with locks around access to those static variables.
But what you want to be doing is pushing the definition of the variable into the highest scope it is used as a local, then pass it as an argument to anything that needs it. This obviously requires alot of work potentially (since it has a cascading effect). You can group similarly needed variables into "context" objects and then pass those around.
See the design pattern Encapsulate Context
If your global vars are truly used only in one function, you're losing nothing by making them into static locals since the fact that they were global anyway made the function that used them non-re-entrant. You gain a little by limiting the scope of the variable.
You should make that change to all globals that are used in only one function, then examine each static local variable to see if it can be made non-static (automatic).
The rule is: if the variable is used in the function before being set, then leave it static.
An example of a variable that can be made automatic local (you would put "int nplus4;" inside the function (you don't need to set it to zero since it's set before use and this should issue a warning if you actually use it before setting it, a useful check):
int nplus4 = 0; // used only in add5
int add5 (int n) {
nplus4 = n + 4; // set
return nplus4 + 1; // use
}
The nplus4 var is set before being used. The following is an example that should be left static by putting "static int nextn = 0;" inside the function:
int nextn = 0; // used only in getn
int getn (void) {
int n = nextn++; // use, then use, then set
return n;
}
Note that it can get tricky, "nextn++" is not setting, it's using and setting since it's equivalent to "nextn = nextn + 1".
One other thing to watch out for: in an RTOS environment, stack space may be more limited than global memory so be careful moving big globals such as "char buffer[10000]" into the functions.
Please give examples of what you call 'global' and 'local' variables
int global_c; // can be used by any other file with 'extern int global_c;'
static int static_c; // cannot be seen or used outside of this file.
int foo(...)
{
int local_c; // cannot be seen or used outside of this function.
}
If you provide some code samples of what you have and what you changed we could better answer the question.
If I understand your question correctly, your concern is that global variables retain their value from one function call to the next. Obviously when you move to using a normal local variable that won't be the case. If you want to know whether or not it is safe to change them I don't think you have any option other than reading and understanding the code. Simply doing a full text search for the the name of the variable in question might be instructive.
If you want a quick and dirty solution that isn't completely safe, you can just change it and see what breaks. I recommend making sure you have a version you can roll back to in source control and setting up some unit tests in advance.

Resources