0

I have two functions. Which one is better and why? I want to run the program in embedded system.

1.

int Flag = 1;
void main(void) {
    /* main body goes here */
}

2.

int Flag;
void main(void) {
    Flag = 1;
    /* main body goes here */
}
Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278
celtspirit
  • 101
  • 1
  • 4
  • Im going wild and say that the inner is better because the space for the variable gets reserved when it's needed this way, instead of being allocated in a very limited stack at the beginning of the program I guess. – Álvaro Gómez Jan 15 '15 at 07:28
  • @ÁlvaroGómez a global is a global, right? then? – Sourav Ghosh Jan 15 '15 at 07:41
  • I don't see a difference w.r.t memory utilization in both the code snippet as the memory allocated is on the data segment for the variable `Flag` at compile time and in the second snippet you are just assigning value `1` to `Flag` if this is not done the global variable will have value `0` – Gopi Jan 15 '15 at 07:46
  • @SouravGhosh I was thinking about local, those don't occupy memory when unitiliazied, globals do, set to 0 by default, so I guess there's not real difference other than the way you organize the code. – Álvaro Gómez Jan 15 '15 at 07:47
  • @ÁlvaroGómez it's about global varibale initialization, whether to _implicit initialize + assign_, or _initialize explicitly_. – Sourav Ghosh Jan 15 '15 at 07:53
  • Vote to close as primarily opinion-based. Define "better" or nobody can answer this question. – Lundin Jan 15 '15 at 13:54
  • @ÁlvaroGómez And how exactly does a local variable in the main() of an embedded system go out of scoop and thereby free stack memory? – Lundin Jan 15 '15 at 14:45

4 Answers4

2

First you should not use a global at all (see A Pox on Globals).

If you insist however, you should prefer the first to ensure that the variable has a valid value for its entire lifetime regardless of how the code is maintained and where and when it is first accessed. The second introduces a maintenance issue where changes of data name or type and addition or removal of variables require changes in two places unnecessarily.

Another issue is that while the variable has an initial value of zero by the language definition, some embedded run-times optionally "optimise" start-up by not initialising global and static data to zero.

Clifford
  • 88,407
  • 13
  • 85
  • 165
  • 1
    It should be noted that because of the mentioned optimization, which is very common but non-standard, you should _never_ write embedded systems code that relies on static initialization. Instead, initialize all variables in "run-time" instead. – Lundin Jan 15 '15 at 14:11
0

The first has less code to execute at runtime, but the cost is one assigment to one global variable which won't be measurable.

In this case, assuming that main() is the entry point for your embedded system, then Flag only needs to be set once, it seems, and that is best done with the initialization.

If, however, you were dealing with another function, call it somefunc(), which is called (directly or indirectly) from main()), and you need Flag to be 1 on each entry tosomefunc() before it calls other functions which look at the value in Flag, then you need to assign to Flag at the top of somefunc().

I assume your embedded environment explicitly supports void main(void) — the standard expects the return type of main() to be int unless the implementation supports other types (and embedded systems might well be different about that).

Community
  • 1
  • 1
Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278
  • Sir about the 3rd paragraph in your answer. I am trying to understand what you mean `and you need Flag to be 1 on each entry tosomefunc() before it calls other functions which look at the value in Flag` what do you mean by this? – Gopi Jan 15 '15 at 08:09
  • Sometimes, you call a function (such as `somefunc()`) many times in a loop. Sometimes, a function such as `somefunc()` must ensure that the initial conditions for its processing are met by setting `Flag = 1;` at the top of its code, before it calls other functions which look at and modify the value stored in `Flag`. If you don't initialize `Flag` in the function, your code starts the new call with whatever value `Flag` had at the end of the previous call. In such cases, it is important to ensure that modifiable globals are set correctly before starting the processing cycle. That's all. – Jonathan Leffler Jan 15 '15 at 08:12
  • Put succinctly: 'initialize when you can; assign when you must'. The issue is then determining when initialization is sufficient and when assignment is necessary. – Jonathan Leffler Jan 15 '15 at 08:14
  • Also note that if you don't explicitly initialize `Flag`, it will be implicitly initialized to 0. That happens with all global variables. – Jonathan Leffler Jan 15 '15 at 08:15
  • Yes sir for the last comment I have already mentioned that in my comment to the answer – Gopi Jan 15 '15 at 08:16
  • There is not much in this answer that makes any sense for an embedded system. It is an embedded system, thus likely it has true NVM. Meaning the first code does execute exactly the same amount of code in runtime as the second, as there is a copy-down execution from flash to RAM. main() is never the entry point on a bare bone (freestanding) system. Also, void main (void) is perfectly fine in standard C and the most likely type, [read this](http://stackoverflow.com/questions/5296163/why-is-the-type-of-the-main-function-in-c-and-c-left-to-the-user-to-define/5296593#5296593). – Lundin Jan 15 '15 at 13:58
0
int Flag = 1;
void main(void) {
    /* main body goes here */
}

Here the memory is allocated in the data segment and that memory exists until the end of the program so this is unneccessary if this is Flag is requried only in the main()

Then you can do

void main(void) {
    int Flag = 1;
    /* main body goes here */
}

Now the variable Flag is allocated memory on the stack and used within main() and the scope of the varible is just within main()

Now your question:

Which one is better and why?

As said in my comment both code snippets shown in your code doesn't have any impact on the memory utilization and as already said the first one has less instruction at execution time as there is no assignment statement int Flag =1 inside main() and the second one has this assignemnt and there will be extra execution for this statement.

Gopi
  • 19,784
  • 4
  • 24
  • 36
  • IMO, its not about the _scope_ of the variable. It is _said_ to be global. – Sourav Ghosh Jan 15 '15 at 07:51
  • @SouravGhosh Just trying to give as much info as possible about what happens along with answering the exact question – Gopi Jan 15 '15 at 08:01
  • Well, 'till my comment, the later part was not there. :-) – Sourav Ghosh Jan 15 '15 at 08:02
  • @SouravGhosh Was typing out the whole stuff so posted the fist copy with info and later addressed the actual issue on hand – Gopi Jan 15 '15 at 08:03
  • It is an embedded system and thus likely got true NVM, meaning that the copy down of static variables from flash to RAM has to be executed in runtime. – Lundin Jan 15 '15 at 14:10
  • @Lundin Even on an embedded system it is good to avoid global variables until it is required right? also global variables will be allocated space in the data-segment during compilation right? – Gopi Jan 15 '15 at 14:34
  • @Gopi Global non-constant variables never make sense anywhere. However, file scope variables or global constants make a lot of sense. All file scope variables end up in the .data segment, given that they are initialized explicitly. Otherwise they end up in the .bss segment. – Lundin Jan 15 '15 at 14:40
0

For this specific case use int Flag = 1;

It does not make sense at all when you initialize the variables 1 by 1, because the code to initialize it ends up taking up just as much if not more .data to accomplish the task.

int lookup_table[8192]; makes sense when you are generating a lookup table from a loop and want to minimize the binary size (if you have limited flash), since nothing gets added to your binary. A good example of this would be a frequently used 8k lookup table involving slow functions (eg. floating point trig functions) that can be loop-initialized once at startup so that the 8k*sizoeof(int) table doesn't get stored in the binary. (See various mp3 decoder implementations for examples)

Note: the loop initialization of the lookup table will still take as much memory to store as well as requiring additional startup time the first time it is used (and therefore initialized), but will reduce binary size and could actually reduce startup times if that specific table is large and uncommonly used.

int lookup_table[8192] = { ... }; makes sense if you are on an embedded system with a generous amount of XIP (execute-in-place) capable flash. Pre-generating will not only eliminate the additional startup time, but since it is XIP, no RAM will be used, but at the expense of a larger binary.

technosaurus
  • 7,676
  • 1
  • 30
  • 52