Not Keil specific; one for the 'C' experts:
Why would one put 'static' variables definitions in a header?
eg, in a header file:
/* * TCO count to temperature conversion table. */ static erTcoTableStruct tcoTableOPUS1[] = { /*{TCO,Temp,} */ {1,-99}, {4,-45}, {5,-40}, {8,-35}, {11,-30}, {16,-25}, {22,-20}, {29,-15}, {37,-10}, {48,-5}, {61,0}, {78,5}, {99,10}, {124,15}, {153,20}, {188,25}, {227,30}, {270,35}, {315,40}, {365,45}, {420,50}, {481,55}, {549,60}, {625,65}, {710,70}, {805,75}, {910,80}, {1010,85}, {1060,88} };
AIUI, the whole point of so-called "header" files in 'C' is to share stuff between source files;
But the whole point of the 'static' keyword (at file scope) in 'C' is to make stuff private so that it is not visible to other modules - ie, not shared.
So I can't see why one would want to have 'static' definitions in a header?!
Actually, they will be caught by the Linker!
And nothing can catch the error where you thought your were accessing the 'x' in this.c but you're actually accessing the 'x' in that.c...
I don't always agree with MISRA.
But since you & Tamir bring up the 'same name' issue, you must realize that the compiler shall complain if it doesn't appear in the 'extern' area in addition to the data-allocation area. So such maintenance shall be caught by the compiler.
--Cpt. Vince Foster 2nd Cannon Place Fort Marcy Park, VA
Andy,
I think that 'static' does not mean 'private' unless you are declaring a function. Static, from what I remember, means that the data allocation remains in memory and is not optimized out. Thus an 'extern' to a static should be allowed.
Yes, there is merit in having a single header that provides (by conditional compilation) both the definitions and the extern declarations of shared symbols - the practice is quite common.
Just to note that the code in question (in my original post) is not doing any of this definition-here-declaration-there trickery; It's just a straightforward 'static' definition that is included verbatim in any & every file that #includes that header.
I agree: having identically-named and identically-typed but distinct objects sounds very dodgy to me!
I think MISRA frowns upon it - even for automatic variables?
Tamir,
Although it might look 'complicated' it really isn't. All too many times people will re-include files that don't need to be included, and will sometimes include the wrong file (esp the SFR files).
Using my method, the code is very structured and all include files are in total control via the "Includes.H" file.
This also adds to the reliability of the code, not to mention repeatability during the debug phase.
Any code-monkey who cannot handle this structure should be taken out back and, well you get the idea.
I think once you have tried it, you'll stick with it.
Dear Captain,
I think that doing what you propose really harms the chance of a less-informed "code-monkey" to correctly maintain C code. I mean, I have encountered too many software spaghettization instances so far, due to: * Incompetence * Sloth * A bad character * Job security * Arrogance
I don't want to add "control freak" to this list :-) :-) :-)
I think you can, but I might be rusty on my "C." I only say that because you (ANDY) are an excellent embedded guy, and therefore I *might* be wrong on the extern to a static.
Although the use of static CAN be circumvented, as shown, it is still not conforming with the C spec:
(1) An identifier declared in different scopes or in the same scope more than once can be made to refer to the same object or function by a process called linkage. There are three kinds of linkage: external, internal, and none.
(2) In the set of translation units and libraries that constitutes an entire program, each declaration of a particular identifier with external linkage denotes the same object or function. Within one translation unit, each declaration of an identifier with internal linkage denotes the same object or function. Each declaration of an identifier with no linkage denotes a unique entity.
3 If the declaration of a file scope identifier for an object or a function contains the storage class specifier static, the identifier has internal linkage.
Therefore, declaring static - by definition above - forces/restricts the identifier to be internal.
Sorry about being nit-picky.
#ifdef UART_Module .-----------------------------------------------. ; TCO count to temperature conversion table. ; '-----------------------------------------------' static erTcoTableStruct tcoTableOPUS1[] = { /*{TCO,Temp,} */ {1,-99}, {4,-45}, {5,-40}, {8,-35}, {11,-30}, {16,-25}, {22,-20}, {29,-15}, {37,-10}, {48,-5}, {61,0}, {78,5}, {99,10}, {124,15}, {153,20}, {188,25}, {227,30}, {270,35}, {315,40}, {365,45}, {420,50}, {481,55}, {549,60}, {625,65}, {710,70}, {805,75}, {910,80}, {1010,85}, {1060,88} }; /* ============================================ ** ** NON-Module Specific (Externs) ** ** ============================================ */ #else // not included by "UART.C" but referenced... // NOTE: "erTooTableStruct" is structured in "Structures.H" extern erTooTableStruct tooTableOPUS1[ MAX_ROWS ][ MAX_COL ]; #endif
That won't work - you can't have an extern reference to something that was declared static!
Again,
Total Control
Why would you want to have distinct but identically-named and identically-typed objects in multiple files??
All data allocation on a module basis should be kept in a header file.
What am I missing?
This could make some sense if each copy of the table had to be modified individually. The other possibility is that the author of the code didn't want to make the table 'global', so only the files that include the header can access it. Some kind of phobia of global variables. Either way, it looks strange.
But why would you ever want to do that?
View all questions in Keil forum