2

I am aware of the various meaning of the static keyword in C, but my question is more specific: Is there any valid reason to declare some variables in the main() function of an embedded C-language program as static?

Since we are talking about variables declared inside the braces of main(), the scope is already local to main(). As regards persistence, the main function is at the top of the call stack and can't exit as long as the program is running. Hence, on the face of it, there would seem to be no valid reason to declare using static inside of main().

However, I notice that an effect of using static declarations is to keep variables and arrays from being placed on the stack. In cases of a limited stack size, this could be important.

Another possible, but rather uncommon case is that of main() calling itself recursively, where you might need some variables to persist at different levels of the recursion.

Are there any other possible valid reasons to use static declarations of variables inside the body of a main() function?

  • *"keep variables and arrays from being placed on the stack"* You answered your own question right there. (Side note: there is never a legitimate reason to call `main` recursively.) – user3386109 Jun 24 '16 at 22:38
  • 1
    The main one is the stack usage. Out of curiosity, why are you asking? – Marc L. Allen Jun 24 '16 at 22:38
  • 1
    @user3386109 -- Does that matter? It's C! We do it because we can! – Marc L. Allen Jun 24 '16 at 22:39
  • 1
    @MarcL.Allen lol, that *is* the problem with C and newbies, too many things we *can* do. – user3386109 Jun 24 '16 at 22:43
  • 1
    The valid reason to do it is that the language allows `static` variables inside `main()`. The valid reason not to is that it rarely achieves anything of use, other than a means of controlling stack usage. I would qualify user3386109's comment as "there is almost never a legitimate reason to call `main()` recursively" - one legitimate reason is to demonstrate why alternatives are better. – Peter Jun 24 '16 at 23:04
  • 1
    The C standard does not mandate a stack and there are indeed implementations which don't use a stack (for variables). And what do you mean with "embedded C-program"? A C program embedded somehwere? Or a C program for an embedded system? And which system? freestanding of hosted? – too honest for this site Jun 24 '16 at 23:16
  • This question was triggered because I have declared almost every variable and array in my main() function as static in a freestanding implementation on a 90MHz RISC CPU. I am sharing code-writing duties with a colleague who mentioned that this seemed like an oddity and that anyone who inherited the code and saw those multiple static declarations would consider it an indication that the original programmer lacked competence. – Charles Razzell Jun 25 '16 at 15:43
  • @CharlesRazzell " I have declared almost every variable and array in my main() function" That sounds like a potentially fishy program design. Is this because all your ADTs and drivers etc use caller allocation? – Lundin Jun 27 '16 at 06:30

8 Answers8

2

.. valid reasons to use static declarations of variables inside the body of a main() function?

  1. Initialization

    int main(void) {
      static int a;  // initialized to 0
      int b;  // uninitialized
    
  2. In C, main() call be called. ref So the usual issues about static variables apply.

    int main(void) {
      static int c;  // Only one instance
      int d;         // One instance per call
      ...
      main();
    
  3. Memory location. Various compilers will organize main()'s variable. It is not specified by C, so a compiler dependent issue.

Community
  • 1
  • 1
chux - Reinstate Monica
  • 143,097
  • 13
  • 135
  • 256
2

A variable has three attributes besides type:

  • Scope (visibility)
  • Life-time
  • Location

Selection of these attributes is best done according to the semantics of the code. While while a static variable in main() may appear to have the same scope and lifetime as a non-static so differ only in location, it does not have the same semantics. If - as is likely under development - you decide to move or reorganise the code in main() into a sub-routine, the use of static will cause such code to behave differently and potentially incorrectly.

My advice therefore is that you use the same determination of the use of static in main() as you would any other function and not treat it as a special case semantically identical to a non-static. Such an approach does not lead to reusable or maintainable code.

You have to partition the memory into stack, heap and static space in any case, if you have a stack variable with a lifetime of the entire process you rob Peter to pay Paul by using more stack in exchange for less static space, so it is not really an argument, except for the fact that insufficient memory is then a build-time issue rather then run-time, but if that is a serious concern, you might consider making all or most variables static as a matter of course (necessarily precluding reentrancy, and thus recursion and multi-threading). If stack space were truly an issue, recursion would be a bad idea in any case - it is a bad idea in most cases already, and certainly recursion of main().

Clifford
  • 88,407
  • 13
  • 85
  • 165
2

I see a practical reason to declare a static variable inside  main (with most compilers on most desktop or laptop operating systems): a local variable inside main is consuming space on the call stack. A static variable consumes space outside the call stack (generally in the .bss or .data segment, at least in ELF executables)

That would make a big difference if that variable takes a lot of space (think of an array of million integers).

The stack space is often limited (to one or a few megabytes) on current (desktop, laptop, tablet) systems.

On some embedded processors, the stack is limited to less than a kilobyte.

Basile Starynkevitch
  • 223,805
  • 18
  • 296
  • 547
0

I think you have said it. It one makes them static which for main() is not very interesting, second it makes them what I call local globals, it essentially puts them in .data with the globals (and not on the stack), but restricts their scope of access like a local. So for main() I guess the reason is to save some stack. If you read around stack overflow though it seems like some compilers put a big stack frame on main() anyway, which most of the time doesnt make sense, so are you really saving any space? Likewise if they are on the stack from main unless you recursively call main they are not taking any more or less space being in .data vs the stack. if they are optimized into registers, then you still burn the .data where you wouldnt have burned the stack space, so it could cost you a little space.

old_timer
  • 69,149
  • 8
  • 89
  • 168
0

The result of trying to indirectly access an object defined with automatic storage duration, i.e. a local variable, in a different thread from which the object is associated with, is implementation defined (see: 6.2.4 Storage duration of objects, p5).

If you want your code to be portable you should only share with threads objects defined with static, thread, or allocated storage duration.

In this example, the automatic object defined in the main should have been defined with static:

int main( void )
{
    CreateThreads();
    type object = { 0 };   //missing static storage-class specifier
    ShareWithThreads( &object );
}
2501
  • 25,460
  • 4
  • 47
  • 87
  • Why the downvote on a correct answer that draws information from the official Standard? – 2501 Jun 26 '16 at 09:17
0

As already mentioned, the main reason would be to save stack space and also give you a better idea of the actual stack size need of your program.

Another reason to declare such variables static would be program safety. There are various embedded system design rules that need to be considered here:

The stack should always be memory-mapped so that it grows towards invalid memory and not towards .bss or .data. That means that in case of stack overflow, there is a chance for the program to raise an exception, rather than going Toyota all over your static variables.

For similar reasons, you should avoid declaring large chunks of data on the stack, as that makes the code more prone to stack overflows. This applies particularly to small, memory-constrained microcontroller systems.


Another possible, but rather uncommon case is that of main() calling itself recursively

That's nonsense, no sane person would ever write such code. Using recursion in an embedded system is very questionable practice and usually banned by coding standards. Truth is, there are very few cases where recursion makes sense to use in any program, embedded or not.

Lundin
  • 195,001
  • 40
  • 254
  • 396
-1

Once reason is that the offset of a static variable in the executable file is determined at link time and can be relied upon to be at the same place.

Therefore, a useful purpose of a static variable at the main level is to include program version data as readable strings or binary readable data that later can be used to analyze/organize executables without needing to have the original source code or any program-specific utilities, other than a hex dump program. We used this hack back in the day when deploying programs where the target system could not be relied upon to have any development tools.

For example,

int main(void)
{
    // tag to search for revision number
    static char versionID[3] = {'V','E','R'};
    // statically embedded program version is 2.1
    static unsigned char major_revision = 2;
    static unsigned char minor_revision = 1;

    printf("\nHello World");
    return 0;
}

Now the version of the program can be determined without running it:

$ od -c -x hello-world | grep "V E R"

0010040 001 002 V E R G C C : ( U b u n t

Rick4Real
  • 34
  • 4
  • No, you are mistaking the layout in running memory for the storage in the executable file. The latter is the work of the linker, and fixed at build time. – Chris Stratton Jun 26 '16 at 04:14
-2

Actually, there's an enormous reason!

If you declare a variable as static within main() (or, any function ...), you are declaring that this local variable is also static.

What this means is that, if this function calls itself ... (which main() probably wouldn't do, although it certainly could ...) ... each recursive instance would see the same value, because this variable isn't being allocated on the stack. (Because, ummm, "it is static!")

"Stack size" is not a valid reason to use static. (In fact, it has nothing to do with it.) If you're concerned about having room "on the stack" to store something, the correct thing to do is to "store it in the heap, instead," using a pointer variable. (Which, like any variable, could be static, or not.)

Mike Robinson
  • 8,490
  • 5
  • 28
  • 41
  • 1
    Heh.. back in the day, it was a luxury to have heap in an embedded system. – Marc L. Allen Jun 24 '16 at 23:07
  • Yep. Hell, "back in the **day,**" ... (koff, koff, TRULY "old-phart" here) ... we somehow managed to perform miracles with KILO-bytes!" **:-D** ("These *kids* today ...") – Mike Robinson Jun 24 '16 at 23:30
  • You'll pry my KIM-1 or my Apple-1 motherboard *(yes, I have one ... bought it, way back then ...)* from my cold, dead fingers. **;-)** – Mike Robinson Jun 25 '16 at 15:37