Is a global or static declaration safer in an embedded environment? - c

I have a choice to between declaring a variable static or global.
I want to use the variable in one function to maintain counter.
for example
void count()
{
static int a=0;
for(i=0;i<7;i++)
{
a++;
}
}
My other choice is to declare the variable a as global.
I will only use it in this function count().
Which way is the safest solution?

It matters only at compile and link-time. A static local variable should be stored and initialised in exactly the same way as a global one.
Declaring a local static variable only affects its visibility at the language level, making it visible only in the enclosing function, though with a global lifetime.
A global variable (or any object in general) not marked static has external linkage and the linker will consider the symbol when merging each of the object files.
A global variable marked static only has internal linkage within the current translation unit, and the linker will not see such a symbol when merging the individual translation units.

The internal static is probably better from a code-readability point of view, if you'll only ever use it inside that function.
If it was global, some other function could potentially modify it, which could be dangerous.

Either using global or static variable within a function both are not safe because then your function will no longer be re-entrant.
However if you are not concerned with function being re-entrant then you can have either based on your choice.

If the variable is only to be accessed within the function count() then it is by definition local, so I cannot see why the question arises. As a rule, always use the most restrictive scope possible for any symbol.
You should really read Jack Ganssle's article A Pox on Globals, it will be enlightening.

Always reduce scope as far as possible. If a variable doesn't need to be visible outside a function, it should not be declared outside it either. The static keyword should be used whenever possible. If you declare a variable at file scope, it should always be static to reduce the scope to the file it was declared in. This is C's way of private encapsulation.
The above is true for all systems. For embedded there is another concern: all variables declared as static or global must be initialized before the program is started. This is enforced by ISO C. So they are always set either to the value the programmer wants them initialized to. If the programmer didn't set any value they are initialized to zero (or NULL).
This means that before main is called, there must be a snippet executed in your program that sets all these static/global values. In an embedded system, the initialization values are copied from ROM (flash, eeprom etc) to RAM. A standard C compiler handles this by creating this snippet and adding it to your program.
However, in embedded systems this snippet is often unfortunate, as it leads to a delay at program startup, especially if there is lots of statics/globals. A common non-standard optimization most embedded compilers support, is to remove this snippet. The program will then no longer behave as expected by the C standard, but it will be faster. Once you have done this optimization, initialization must be done in runtime, roughly static int x; x=0; rather than static int x=0;.
To make your program portable to such non-standard embedded compilers, it is a good habit to always set your globals/statics in runtime. And no matter if you intend to port to such compilers or not, it is certainly a good habit not to rely on the default zero initialization of globals/statics. Because most rookie C programmers don't even know that this static zero initialization rule exists and they will get very confused if you don't init your variables explicitly before using them.

i dont think is there is anything special with static & normal global with embedded domain ...!!
in one way static is good that if you are going to initialize your counter as o in starting then if you just declare with static then there is no need to initialize with it 0 because every static varaible is by default initialized with 0.
Edit :
After Clifford's comment i have checked and get to know that globals are also statically allocated and initialised to zero, so that advantage does not exist..

Pass a pointer to a "standard" variable instead
void count(int *a) {
int i;
for (i = 0; i < 7; i++)
{
(*a)++;
}
}
This way you do not rely neither on global variables nor on static local variables, which makes your program better.

I would say static is better than global if you want only one function to access it in which you declared it . Plus global variables are more prone to be accidentally accessed by other functions.
If you do want to use globals since it can be accessed by other functions in the program, make sure you declare them as volatile .
volatile int a = 0;
volatile makes sure it is not optimised by compilers in the wrong way.

Related

Embedded C: Risk of Initializing global data

General question in c langage:
Is it safe to initialize data in the declaration?
example:
static unsigned char myVar =5u;
Is there any risk that this value will be overwritten by the startup code?
Generally, embedded systems microcontroller projects come in two flavours and the IDE often lets you pick one:
Standard C compliant (sometimes referred to as "ANSI" by confused tool vendors).
Minimized start-up.
The former, standard C compliant projects require that all variables with static storage duration, such as those declared at file scope and/or with the keyword static are initialized before main() is called. This initialization happens inside the start-up code ("C run-time"/"CRT"). On such a system, the myVar = 5u; is guaranteed to be written (not overwritten) by the start-up code. It copies down the value 5 from flash to RAM.
The latter, "mimizined"/"fast" start-up version is not strictly C standard compliant. In such projects all the initialization code of static storage duration variables is simply removed. This to reduce the time from reset to when main() is called. On such systems, nothing will execute the static unsigned char myVar =5u; code - your variable remains uninitialized and indeterminate even though you explicitly initialized it. You have to set it manually at "run-time", which is usually done from some init "constructor" code.
If you have static uint8_t foo_count; belonging to foo.c, then the foo module will have to provide a function foo_init() from where the code foo_count = 5; is executed.
Since the "minimized start-up" version is very common in embedded systems, it is usually considered dangerous to rely on default initialization of static storage duration variables, in case the code gets ported to such a system.
I hope your start up code runs before main. with that said, when you declare the variable static, the variables scope is bound to the scope of that translation unit (somefile.c), so yes you could overwrite it but that would be hard to do from other units (direct memory assignment) The golden rule for embedded systems is to avoid global variables but if you most, declare global variables as externs in a header file where it makes the most sense to put it.
Alternatively you could replace this with a #define.
#define MY_VAR 5U
The start up code is what is responsible for applying the initialisation (where did you imagine that was done?), so yes it is safe and with respect to initialisation best practice.
Without initialisation a static or global should have a value of zero. It is not unheard of for the startup code in some embedded systems to deliberately omit zero initialisation in order to minimise start up time. Normally that would not be the default startup code, and you would have to make a conscious decision to use it. It is unsafe and unfair to later maintainers who might be unaware is such non-standard behaviour. It is also in most cases an unnecessary and premature optimisation. Nonetheless you might initialise all such variables, even if the unit is zero, to defend against such non standard startup (whilst also rendering it pointless, which it generally is).
What is not best practice is the use of a global in the first instance (https://www.embedded.com/a-pox-on-globals/). Though to be fair the myVar in question is not truly global in this case.
This may not be directly related with the original question, but I think it's worth mentioning:
Initialization of a global variable using another global variable from a different translation unit is not safe. For example:
In a.c
unsigned var_from_a = 5u;
In b.c
extern unsigned var_from_a;
unsigned var_from_b = var_from_a;
There is no guarantee that var_from_b becomes 5u, because the initialization order of translation units is not defined. If you're unlucky, b.c is processed before a.c, and var_from_b may become 0 or some other garbage value, while a.c is processed later and var_from_a properly initialized to 5u.
I'm not sure if it would change this behavior if var_from_a was defined as const.

What is the use of Static local variable when we can get a global variable at the same cost?

In C ,what is the use of static storage class when an external variable can serve its purpose at the same cost ie. both occupy storage space in the data segment of the executable.
I have much better scope with external variable.If i want the scope of external variable to be specific file i do not declare this variable else where.i see a lot of flexibility with a global variable that static local variable
And we can refer to local static variable outside the function if we have the address of the variable.Memory for local static variable will be in Data segment not in the stack frame of the function.So unique feature does static storage class bring to the table.
I just want to know whether static has any subtle purpose that i m not aware of.
You write that a global variable has a “better” scope. This is incorrect. It has a bigger scope. Bigger is not better.
Bigger may be necessary, if you need an identifier to be visible in more places, but this is often not the case. But a bigger scope means more exposure to errors. Global variables muddle the semantics of routines by making it harder to see what program state they use and change, and it increases the probability of errors caused by failing to declare a local identifier and of other errors.
In particular, an identifier with external linkage will collide with identifiers in other libraries. Consider what happens when you are writing a physics application, have an external identifier named acceleration, and link with a physics library that also has an external identifier named acceleration. The program will fail. Because of this, external identifiers are usually bad design.
A significant limit on our ability to develop and maintain complex software is human error. Much of programming language semantics limits the language to prevent errors. With a raw computer, you can add two pointers, trash your stack pointer, accidentally load the bytes of a float into an integer register, and so on. Good programming languages make these errors difficult to do by mistake.
Global variables were a larger source of errors before scoping rules helped control them. Good programmers limit the scopes of their identifiers.
A global variable is well, global, it can be accessed from anywhere.
A static local variable has local scope. It is static, so it's lifetime runs across the lifetime of the application however it can only be accessed from the local scope (whether that scope is a function, a block, or a file)
The basic difference is on scope of variable.
1) global variable is global for entire project. lets say your project has 10 different files then all 10 files can access the global variable(see how to use extern).
2) static variable/function can be used by function/file within which it is defined. It cannot be used by any other file in your project.
yet, you can modify the static variable(defined in func1()) in func2() by passing reference of the variable. please look into below example,
void func2(int *i)
{
(*i)++;
}
void func1()
{
static int i;
i=1;
printf("%d\n", i);
func2(&i);
printf("%d\n", i);
}
int main()
{
func1();
return 0;
}
As you see above, func1() has static int i which cannot be directly manipulated by func2(), but if you pass reference of the variable you can still manipulate the variable like ordinary variable.
hope it helps...
Difference between local and global first and foremost is the scope: you can access local variables only from within the block they're defined in, while global variables can be accessed from anywhere. Consequently, you can only have one variable with a given name in global scope, but you can have multiple local static variables in different functions.
As with static global variables versus extern variables: yes, static global variables are local to the translation unit (i.e. the .c source file they're defined in).
So the main concern here is the notion of scope, and the storage comes naturally from there.
The reason you should use a local static variable is scope, and therefore avoiding some bug prone situations since using a local static variable you'll not be able to refer to it outside the function it was defined in.
Here's a short program which demonstrates the difference:
#include <stdio.h>
static int a=20;
void local()
{
printf("%d,addr:%d \n", a, (void*)&a);
a = 100;
}
int main()
{
{
static int a = 10;
printf("%d,addr:%d \n", a, (void*)&a);
local();
}
printf("%d addr:%d \n", a, (void*)&a);
}
Output:
10,addr:134518604 -- local static inside the braces
20,addr:134518600 -- this is referring the global static variable
100 addr:134518600 -- This is referring the global static variable which is outside of
the braces.
Here braces also matters: if no braces in the main() function then it refers local static variable only.

Pointer to function vs global variable

New EE with very little software experience here.
Have read many questions on this site over the last couple years, this would be my first question/post.
Haven't quite found the answer for this one.
I would like to know the difference/motivation between having a function modify a global variable within the body (not passing it as a parameter), and between passing the address of a variable.
Here is an example of each to make it more clear.
Let's say that I'm declaring some functions "peripheral.c" (with their proper prototypes in "peripheral.h", and using them in "implementation.c"
Method 1:
//peripheral.c
//macros, includes, etc
void function(*x){
//modify x
}
.
//implementation.c
#include "peripheral.h"
static uint8 var;
function(&var); //this will end up modifying var
Method 2:
//peripheral.c
//macros, includes, etc
void function(void){
//modify x
}
.
//implementation.c
#include "peripheral.h"
static uint8 x;
function(); //this will modify x
Is the only motivation to avoid using a "global" variable?
(Also, is it really global if it just has file scope?)
Hopefully that question makes sense.
Thanks
The function that receives a parameter pointing to the variable is more general. It can be used to modify a global, a local or indeed any variable. The function that modifies the global can do that task and that task only.
Which is to be preferred depends entirely on the context. Sometimes one approach is better, sometimes the other. It's not possible to say definitively that one approach is always better than the other.
As for whether your global variable really is global, it is global in the sense that there is one single instance of that variable in your process.
static variables have internal linkage, they cannot be accessed beyond the translation unit in which they reside.
So if you want to modify a static global variable in another TU it will be have to be passed as an pointer through function parameter as in first example.
Your second example cannot work because x cannot be accessed outside implementation.c, it should give you an compilation error.
Good Read:
What is external linkage and internal linkage?
First of all, in C/C++, "global" does mean file scope (although if you declare a global in a header, then it is included in files that #include that header).
Using pointers as parameters is useful when the calling function has some data that the called function should modify, such as in your examples. Pointers as parameters are especially useful when the function that is modifying its input does not know exactly what it is modifying. For example:
scanf("%d", &foo);
scanf is not going to know anything about foo, and you cannot modify its source code to give it knowledge of foo. However, scanf takes pointers to variables, which allows it to modify the value of any arbitrary variable (of types it supports, of course). This makes it more reusable than something that relies on global variables.
In your code, you should generally prefer to use pointers to variables. However, if you notice that you are passing the same chunk of information around to many functions, a global variable may make sense. That is, you should prefer
int g_state;
int foo(int x, int y);
int bar(int x, int y);
void foobar(void);
...
to
int foo(int x, int y, int state);
int bar(int x, int y, int state);
void foobar(int state);
...
Basically, use globals for values that should be shared by everything in the file they are in (or files, if you declare the global in a header). Use pointers as parameters for values that should be passed between a smaller group of functions for sharing and for situations where there may be more than one variable you wish to do the same operations to.
EDIT: Also, as a note for the future, when you say "pointer to function", people are going to assume that you mean a pointer that points to a function, rather than passing a pointer as a parameter to a function. "pointer as parameter" makes more sense for what you're asking here.
Several different issues here:
In general, "global variables are bad". Don't use them, if you can avoid it. Yes, it preferable to pass a pointer to a variable so a function can modify it, than to make it global so the function can implicitly modify it.
Having said that, global variables can be useful: by all means use them as appropriate.
And yes, "global" can mean "between functions" (within a module) as well as "between modules" (global throughout the entire program).
There are several interesting things to note about your code:
a) Most variables are allocated from the "stack". When you declare a variable outside of a function like this, it's allocated from "block storage" - the space exists for the lifetime of the program.
b) When you declare it "static", you "hide" it from other modules: the name is not visible outside of the module.
c) If you wanted a truly global variable, you would not use the keyword "static". And you might declare it "extern uint8 var" in a header file (so all modules would have the definition).
I'm not sure your second example really works, since you declared x as static (and thus limiting its scope to a file) but other then that, there are some advantages of the pointer passing version:
It gives you more flexibility on allocation and modularity. While you can only have only one copy of a global variable in a file, you can have as many pointers as you want and they can point to objects created at many different places (static arrays, malloc, stack variables...)
Global variables are forced into every function so you must be always aware that someone might want to modify them. On the other hands, pointers can only be accessed by functions you explicitely pass them to.
In addition to the last point, global variables all use the same scope and it can get cluttered with too many variables. On the other hand, pointers have lexical scoping like normal varialbes and their scope is much more restricted.
And yes, things can get somewhat blurry if you have a small, self contained file. If you aren't going to ever instantiate more then one "object" then sometimes static global variables (that are local to a single file) work just as well as pointers to a struct.
The main problem with global variables is that they promote what's known as "tight coupling" between functions or modules. In your second design, the peripheral module is aware of and dependent on the design of implementation, to the point that if you change implementation by removing or renaming x, you'll break peripheral, even without touching any its code. You also make it impossible to re-use peripheral independently of the implementation module.
Similarly, this design means function in peripheral can only ever deal with a single instance of x, whatever x represents.
Ideally, a function and its caller should communicate exclusively through parameters, return values, and exceptions (where appropriate). If you need to maintain state between calls, use a writable parameter to store that state, rather than relying on a global.

Why declare a variable or function static in C?

I understand what static does, but not why we use it. Is it just for keeping the abstraction layer?
There are a few reasons to use static in C.
When used with functions, yes the intention is for creating abstraction. The original term for the scope of a C source code file was "translation unit." The static functions may only be reached from within the same translation unit. These static functions are similar to private methods in C++, liberally interpreted (in that analogy, a translation unit defines a class).
Static data at a global level is also not accessible from outside the translation unit, and this is also used for creating an abstraction. Additionally, all static data is initialized to zero, so static may be used to control initialization.
Static at the local ("automatic") variable level is used to abstract the implementation of the function which maintains state across calls, but avoids using a variable at translation unit scope. Again, the variables are initialized to zero due to static qualification.
The keyword static has several uses; Outside of a function it simply limits the visibility of a function or variable to the compilation unit (.c file) the function or variable occurs in. That way the function or variable doesn't become global. This is a good thing, it promotes a kind of "need to know" principle (don't expose things that don't need to be exposed). Static variables of this type are zero initialized, but of course global variables are also zero initialized, so the static keyword is not responsible for zero initialization per se.
Variables can also be declared static inside a function. This feature means the variable is not automatic, i.e. allocated and freed on the stack with each invocation of the function. Instead the variable is allocated in the static data area, it is initialized to zero and persists for the life of the program. If the function modifies it during one invocation, the new modified value will be available at the next invocation. This sounds like a good thing, but there are good reasons "auto" is the default, and "static" variables within functions should be used sparingly. Briefly, auto variables are more memory efficient, and are essential if you want your function to be thread safe.
static is used as both a storage class specifier and a linkage specifier. As a linkage specifier it restricts the scope of an otherwise global variable or function to a single compilation unit. This allows, for example a compilation unit to have variables and functions with the same identifier names as other compilation units but without causing a clash, since such identifiers are 'hidden' from the linker. This is useful if you are creating a library for example and need internal 'helper' functions that must not cause a conflict with user code.
As a storage class specifier applied to a local variable, it has different semantics entirely, but your question seems to imply that you are referring to static linkage.
Static functions in C
In C, functions are global by default. The “static” keyword before a function name makes it static. For example, below function fun() is static.
static int fun(void)
{
printf("I am a static function ");
}
Unlike global functions in C, access to static functions is restricted to the file where they are declared. Therefore, when we want to restrict access to functions, we make them static. Another reason for making functions static can be reuse of the same function name in other files.
For example, if we store following program in one file file1.c
/* Inside file1.c */
static void fun1(void)
{
puts("fun1 called");
}
And store following program in another file file2.c
/* Iinside file2.c */
int main(void)
{
fun1();
getchar();
return 0;
}
Now, if we compile the above code with command gcc file2.c file1.c, we get the error undefined reference to fun1. This is because fun1 is declared static in file1.c and cannot be used in file2.c. See also the explanation here, where the codes come from.

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