Static struct declaration and initialization in c header file - c

I develop an embedded application which uses the MindTree Bluetooth SDK.
I have the following in a header file:
typedef struct {
UCHAR outputDir;
UCHAR reset;
UCHAR nack;
UCHAR startCondition;
UCHAR stopCondition;
UCHAR busy;
} USCI_ConfigurationFlags;
static USCI_ConfigurationFlags usciConfigFlags = { UCTR, UCSWRST, UCNACKIFG, UCTXSTT, UCTXSTP, UCBBUSY };
Later in two .c files I include the above header and use the usciConfigFlags on different occasions sometimes from within an interrupt.
Is this legal?
I'm trying to understand why(and if it is related to the question) the values of the struct change at runtime, after calling the BT_bluetooth_on method in the SDK.
Thanks,
Adam.

static here doesn't mean what you think it means. It means that the declaration and variable will only be visible in one compilation unit. That is, you have two independent instances of usciConfigFlags.
If you want a global variable, you need to use extern not static and make the actual declaration (without extern) with the initial value in one of your c files.
Also be weary of changing the values in the struct without proper locking. Read-only concurrent access is usually fine.

There is no problem you include the header in two .c file. The static modifier limits the accessible scope of the variable in the file including the header only. The two usciConfigFlags in two different files are not identical.
Also static does not mean constant. So you can modify the value of the structure in whatever way you want.
The following is from wikipedia
In computer programming, a static variable is a variable that has been
allocated statically — whose lifetime extends across the entire run of
the program. This is in contrast to the more ephemeral automatic
variables (local variables), whose storage is allocated and
deallocated on the call stack; and in contrast to objects whose
storage is dynamically allocated.

Prepending a static keyword to a variable makes it visible only in the current translation unit (i.e. if within a function, only that function and if within a file, only that file).
It is never a good idea to define a variable in a header file. Even if you need two static variables in two different files with the same name, it is better that you put in the .c file itself as it helps in better maintaince and readability as you will be clear in which all files it is actually present and is being used.
If you add it in a header file, then at a later point, if some other .c file includes this header, then unneccessarily this variable will included for that translation unit.
Epsalon had suggested other good points which you can consider.

Related

Embedded C. Make a structure extern vs passing it by reference to another source

Not particularly experienced in C, chance made be responsible for a small microcontroller project.
So, i have a structure which resides on a file1.c. Its used by several functions in that file. It was defined as static volatile Structure struct right now.
The struct is declared static because i read on a book called "embedded system development coding reference guide" that "variables accessed by several functions defined in the same file shall be declared with static in the file scope". Well, its used by several functions, and i want it file based so i thought it matches that description. Volatile because it holds some AD reads from some ports.
I also have a file2.c which needs to access values of the same structure.
From my understanding my options are the following
on file1.h define that structure as extern and access
#include file1.h on file2.c and access it.
From my undestanding though,this will make the structure visible to
the whole file2.c even though only 1 function there is going to need
it
keep the structure as is, and make a function in file.2 which accepts
the structure by reference function(Structure *struct), make that
function accessible from file1.c and just pass the value by ref
function(&struct)
Which one is the best approach? I know that both of them work, but is there a specific reason why i should use one and not the other etc?
I want to clarify that the typedef { variables } Structure, is in another header file which is included on both file1.c and file and file2.c, so there is no question about the files recognizing the structure. I am asking which is the best way to access that structure from where is needed.
You need to move the struct definition to an header file otherwise file2.c won’t recognize the struct even you pass it by reference . A reference or a pointer still need a class/struct definition to be compiled...
Based on your clarification, the struct should probably not be volatile qualified. Just because the actual ADC hardware registers are volatile, it doesn't mean that the data read from them has to be. Except if you fill the struct from an ISR or from DMA, but that doesn't sem to be the case(?).
The proper design is then to place the typedef of the struct in the header file and the variable definition in the .c file. Then provide access to the variable through getter/setter functions. However, consider if other code really need to access the struct as is, or if they just need a few values from it. Overall, use private encapsulation and stay away from extern.

Odd C behavior: variable visible when it shouldn't be

In my program, I have a file called constants.h that declares the following matrix in a global scope (the matrix should be fully constant - if anyone sees a potential problem, let me know):
static unsigned char const MY_MATRIX[66][9] = {...};
In another file, let's call it main.c, I can actually reference this constant:
doSomething(var1, count, MY_MATRIX[42], TRUE, FALSE, thing);
But then I just read the definition of the keyword static and it's supposed to mean that the variable cannot be accessed outside the file it's defined in. (In this case, the desired behavior is that it should be accessed, but then it seems the extern keyword is the one to use!)
So, can anyone tell me why this works? Why is the variable not invisible? Thanks!
This is because you are declaring a static variable in a header: when you include the header in a C file, you get a brand-new definition independent of the other definitions. If you include the header in two files, you get two independent copies; if you include it in three C files, you get three independent copies, and so on. The copies do not conflict with each other, because the static definition hides them from the linker.
A proper way to make use of a shared piece of data allocated in a static memory is to make the declaration extern in the header, and then add a non-static definition in exactly one C file.
If it's in a header, it's defined in every single source file you include it in (though each source file will have their own instantiation of it - they don't access the same one).
There are two uses of the static keyword:
A static variable inside a function block keeps its value between subsequent calls.
A static global variable or a function is "visible" only in the file it has been declared in.
Here, you define the matrix in a header file, hence it is visible to all the .c files which include that header file. To restrict its visibility, define it in a .c file instead.
Usually when a static variable is declared in a header file its scope is not limited to .h file meaning nothing like header file scope. The translation unit includes the text from header file in source file. Therefore every translation unit including header file gets its own individual variable though it is static scope.

Accessing a static variable of one compilation unit from others directly, in C

So I'm working on a "quick and dirty" profiler for firmware- I just need to know how long some functions take. Merely printing the time it takes every time will skew the results, as logging is expensive- so I am saving a bunch of results to an array and dumping that after some time.
When working in one compilation unit (one source file), I just had a bunch of static arrays storing the results. Now I need to do this across several files. I could "copy paste" the code, but that would be just ugly (Bear with me). If I put timing code in a seperate compilation unit, make static variables, and provide accessor functions in the header file, I will be incurring the overhead of function calls every time i want to access those static variables.
Is it possible to access static variables of a compilation unit directly?
I've always tried to encapsulate data, and not use global variables, but this situation calls for it simply due to speed concerns.
I hope this makes sense! Thank you!
EDIT: Alright, so it appears what I'm asking is impossible- do any of you see alternatives that essentially allow me to directly access data of another compilation unit?
EDIT2: Thank you for the answers Pablo and Jonathan. I ended up accepting Pablo's because I didn't have clear place to get the pointer to the static data (as per Jonathan) in my situation. Thanks again!
No, it's not possible to access static variables of a compilation unit from another one. static keyword precisely prevents that from happening.
If you need to access globals of one compilation unit from another, you can do:
file1.c:
int var_from_file1 = 10;
file2.c:
extern int var_from_file1;
// you can access var_from_file1 here
If you can remove the static keyword from your declarations, you should be fine. I understand that changing existing source code is not always an option (I.E. dealing with existing legacy compiled code).
To get at the static variables in a compilation unit C1 from another unit C2, some function in C1 must make pointers to the variables available to C2, or some non-static variable must contain a pointer to the static variables.
So, you could package the 'static variables' into a single structure, and then write a function that returns a pointer to that structure; you can call that function to gain access to the static variables.
Similar rules apply to static functions; if some function (or non-static variable) in the file makes the pointers to the functions available, then the static functions can be called indirectly from outside the file.
If access via pointers doesn't count as directly, then you are snookered; static hides and you can't unhide except by removing the keyword static from the variables when the module is compiled - maybe via the C preprocessor. Beware name clashes.

Reasons to use Static functions and variables in C

I wonder about the use of the static keyword as scope limiting for variables in a file, in C.
The standard way to build a C program as I see it is to:
have a bunch of c files defining functions and variables, possibly scope limited with static.
have a bunch of h files declaring the functions and possibly variables of the corresponding c file, for other c files to use. Private functions and variables are not published in the h file.
every c file is compiled separately to an o file.
all o files are linked together to an application file.
I see two reasons for declaring a gobal as static, if the variable is not published in the h file anyway:
one is for readability. Inform future readers including myself that a variable is not accessed in any other file.
the second is to prevent another c file from redeclaring the variable as extern. I suppose that the linker would dislike a variable being both extern and static. (I dislike the idea of a file redeclaring a variable owned by someone else as extern, is it ok practice?)
Any other reason?
Same goes for static functions. If the prototype is not published in the h file, other files may not use the function anyway, so why define it static at all?
I can see the same two reasons, but no more.
When you talk about informing other readers, consider the compiler itself as a reader. If a variable is declared static, that can affect the degree to which optimizations kick in.
Redefining a static variable as extern is impossible, but the compiler will (as usual) give you enough rope to hang yourself.
If I write static int foo; in one file and int foo; in another, they are considered different variables, despite having the same name and type - the compiler will not complain but you will probably get very confused later trying to read and/or debug the code. (If I write extern int foo; in the second case, that will fail to link unless I declare a non-static int foo; somewhere else.)
Global variables rarely appear in header files, but when they do they should be declared extern. If not, depending on your compiler, you risk that every source file which includes that header will declare its own copy of the variable: at best this will cause a link failure (multiply-defined symbol) and at worst several confusing cases of overshadowing.
By declaring a variable static on file level (static within function has a different meaning) you forbid other units to access it, e.g. if you try to the variable use inside another unit (declared with extern), linker won't find this symbol.
When you declare a static function the call to the function is a "near call" and in theory it performs better than a "far call". You can google for more information. This is what I found with a simple google search.
If a global variable is declared static, the compiler can sometimes make better optimizations than if it were not. Because the compiler knows that the variable cannot be accessed from other source files, it can make better deductions about what your code is doing (such as "this function does not modify this variable"), which can sometimes cause it to generate faster code. Very few compilers/linkers can make these sorts of optimizations across different translation units.
If you declare a variable foo in file a.c without making it static, and a variable foo in file b.c without making it static, both are automatically extern which means the linker may complain if you initialise both, and assign the same memory location if it doesn't complain. Expect fun debugging your code.
If you write a function foo () in file a.c without making it static, and a function foo () in file b.c without making it static, the linker may complain, but if it doesn't, all calls to foo () will call the same function. Expect fun debugging your code.
My favorite usage of static is being able to store methods that I wont have to Inject or create an object to use, the way I see it is, Private Static Methods are always useful, where public static you have to put some more time in thinking of what it is your doing to avoid what crazyscot defined as, getting your self too much rope and accidentally hanging ones self!
I like to keep a folder for Helper classes for most of my projects that mainly consist of static methods to do things quickly and efficiently on the fly, no objects needed!

Keeping variables global to the library scope in C

Is there any way to keep global variables visible only from inside a library while inaccessible from programs that access that library in C?
It's not that it is vital to keep the variable protected, but I would rather it if programs couldn't import it as it is nothing of their business.
I don't care about solutions involving macros.
If you use g++, you can use the linker facilities for that using attributes.
__attribute__((visibility("hidden"))) int whatever;
You can also mark everything as hidden and mark explicitly what is visible with this flag: -fvisibility=hidden
And then mark the visible variables with:
__attribute__((visibility("default"))) int whatever;
static int somelocalvar = 0;
that makes somelocalvar visible only from whithin the source file where it is declared (reference and example).
Inside the library implementation, declare your variables like that:
struct my_lib_variables
{
int var1;
char var2;
};
Now in the header for end-users, declare it like that:
struct my_lib_variables;
It declares the structure as an incomplete type. People who will use the header will be able to create a pointer to the struct, but that's all. The goal is that they have to write something like that:
#include "my_lib.h"
struct my_lib_variables* p = my_lib_init();
my_lib_do_something(p);
my_lib_destroy(p);
The libray code is able to modify the variables, but the library can't do it directly.
Or you can use global variables, but put the extern declarations inside a header which will not be used by the end-user.
You can use another header file for exporting functionality to outside modules than you have for the internal functionality and thus you don't have to declare globals that doesn't have to be accessible from outside the module.
Edit:
There is only linker problems if you declare things more than once. There is no need to keep all global data in one header file, in fact, there may be a wise reason top split it up into several smaller pieces for maintainability and different areas of responisiblity. Splitting up into header files for external data and internal data is one such reason and this should not be a problem since it is possible to include more than one header file into the same source file. And don't forget the guards in the header files, this way, collision in linking is mostly avoided.
#ifndef XXX_HEADER_FILE
#define XXX_HEADER_FILE
code
#endif

Resources