Hi everyone,
does anyone know the size between switch-case and if-else loops? which one is bigger in size? or in other words, which of these two occupy more space (in memory) when using?
Hi everyone,
does anyone know the size between switch-case and if-else loops? which one is bigger in size? or in other words, which of these two occupy more space (in memory) when using?
This is like asking, which is faster - Ford or Holden, and does it even matter if all you do is drive to the supermarket two minutes down the road once a week?
There is no "this is better than that" grand statement that we can supply as an answer here sorry.
You show what you are doing, and we can tell you if you're doing it right.
My homepage
Advice: Take only as directed - If symptoms persist, please see your debugger
Linus Torvalds: "But it clearly is the only right way. The fact that everybody else does it some other way only means that they are wrong"
It will depend on the compiler and the target architecture. The compiler may replace a chain of if-else with a switch. It may replace a switch with a chain of if-else. You might find the answer, then upgrade the compiler and the answer is changed.
If you are concerned about code size, most compilers provide switches to request the smallest possible code. The compiler will then make the appropriate decisions for you. Write the code to be clear to humans, let the compiler worry about optimizing it.
Code://try //{ if (a) do { f( b); } while(1); else do { f(!b); } while(1); //}
Not worth worrying about it because correct is better than fast.
The decision itself ("go here, execute that, because of this") is likely to manifest itself as a set of instructions; so you have the size of those impacting the size of the executable on its own. More instructions, more code, more storage space. Then you have data itself which if its not in the executable as hard coded numbers say, like 5, which you would compare against, then it's stored in RAM as variables.
"Which occupies more space ..." well, theoretically, as much as it takes. If your code paths are complicated, they will take up more space than code that is more straightforward. Is it worth worrying about? Not really. It is a good idea to remove dead branches of code (code paths that shouldn't be there). Whether that happens sooner or later depends on your priorities, like, getting your homework done on time.
im trying to optimize my codes. im not using a licensed IDE therefore it doesnt optimize just as much as I would like it to.
main_test_281212.c
I recommend using the Pelles C IDE, simple, free and straight forward. and it seems ALOT of people on here needing help (especially from ITT) seem to be using it!!!
I use it also, i became kind of fond of it. But also use MS VC++ for C++ mostly
Cases which are densely packed (like 1,2,3,4,5) should be more efficiently implemented as switch/cases. Whereas case 1, case 1000, case 1000000 would normally result in the compiler generating the corresponding if / else if chain.
Though if you only have 2 cases, you might be better off with just if / else
If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
If at first you don't succeed, try writing your phone number on the exam paper.
I don't know where is the bottleneck, but...
First, you can reorganize this:
Code:key = 0; if ((adc > 205) && (adc < 235 )) key = 1; else if ((adc > 155) && (adc < 173 )) key = 2; else if ((adc > 80 ) && (adc < 141 )) key = 3; else if ((adc > 47 ) && (adc < 78 )) key = 4; else if ((adc > 0 ) && (adc < 15 )) key = 5;
...like a binary search:
Code:key = 0; if (adc>155) { if (adc<173) key = 2; else if (adc>205 && adc<235) key = 1; } else if (adc<78) { if (adc>47) key = 4; else if (adc>0 && adc<15) key = 5; // <--- longest path } else if (adc>80 && adc<141) key = 3;
The longest path takes 5 comparisons. Though, the code is ugly :-(
I would suggest to use 'if' instead of 'switch', just for clarity... You have few cases.
But... wait a minute... The 'switch(state)' doesn't make any sense! The variable 'state' will always be zero at this point. It is local, you initialized it to zero, you didn't change it... Maybe you meant to make it 'static':
static unsigned char state = 0;
static unsigned char last_key = 0;
For the last switch, I would suggest lookup tables:
Code:static const unsigned char A[]={0xA0,0xC0,0xE8,0xD8,0xB8}; static const unsigned char B[]={0x5F,0x3F,0x17,0x27,0x47}; static const unsigned char C[]={0xC0,0x00}; static const unsigned char D[]={0x3F,0x00}; //... if (key>0) { if (key_event==1) { d1 = A[key-1]; d2 = B[key-1]; } else if (key_event==2 && key<3) { d1 = C[key-1]; d2 = D[key-1]; } }
Anyway, I think that the problem is in the variable 'state'.
And if, for some hardware limitation, your compiler were making this variable static by default, initializing it only once, then the problem could be in the initialization of other local variables.
Both a switch statement and an if...else if...else if...else sequence make a multi-way branching decision. Switch has limitations but is sometimes more concise. Consider an example program: when would it be better to rewrite this type of decision as an if...else if...else if expression? The answer probably does not have anything to do with the resulting size of the binary.
To address binary size: If you want a smaller binary, compile with size optimization and strip the binary from debugging symbols. If you want a very small binary, compile it with the "Tiny C Compiler" (tinycc). If you want the smallest possible binary size, rewrite it as an assembly program.Code:#include <stdio.h> #include <stdlib.h> #include <ctype.h> #define LETTER argv[1] int main(int argc, char *argv[]) { if (argc != 2) { printf("Usage: switchtest LETTER\n"); return EXIT_FAILURE; } char lett = tolower(LETTER[0]); switch(lett) { case 'a': case 'e': case 'i': case 'o': case 'u': case 'y': printf("vowel\n"); break; case 'b': case 'c': case 'd': case 'f': case 'g': case 'h': case 'j': case 'k': case 'l': case 'm': printf("consonant not after m\n"); break; case 'n': case 'p': case 'q': case 'r': case 's': case 't': case 'v': case 'w': case 'x': case 'z': printf("consonant after m\n"); break; default: printf("other\n"); break; } return EXIT_SUCCESS; }
Sorry, I couldn't resist the temptation :-)Code:puts ( strchr("aeiouy",lett) ? "vowel" : lett>='a' && lett<='m' ? "consonant not after m" : lett>'m' && lett<='z' ? "consonant after m" : "other");
You've just got to try. If possible, examine the assembly code the compiler generates (-S with gcc).
The if else ladder has the advantage that you can put the common cases at the start. For example if you're switching on "title" approximately half your sample are likely to be "Mr". Then about 1 sixth will be "Miss", "Mrs" or "Ms", you'll have about 1% Drs and then a sprinkling of Profs, Lords, Rev'ds and maybe one "Her Majesty Queen ...". So put Mr at the top of the ladder, and half the cases are resolved with a single comparison. The compiler has no way of knowing that there are millions of Mrs and only one "Her Majesty" in the entire country.
But the switch version if often optimised with a jump table. This can be faster than comparisons.
So it's a case of code, measure, see the assembly.
I'm the author of MiniBasic: How to write a script interpreter and Basic Algorithms
Visit my website for lots of associated C programming resources.
https://github.com/MalcolmMcLean
The advantage of the switch/case is not in "size". It is that it can typically be implemented as a simple jump table (i.e. examination only once of value being tested, and a jump to a destination based on that value). The advantage is more likely to be in performance than any "size" measure. The down side is that it relies on the values tested being fixed at compile time, and it only works with integral values.
The "size" of the comparison might only be one instruction, but the destination points (i.e. the points jumped to) have to specified in the executable, which means the net size of code the compiler emits for a switch/case can be unpredictable. Depending on the target machine, the instructions for conditional jump might have limits (eg only able to be used for a small number of jump points) which means the compiler might have to break things up (eg with the equivalent of nested if/else and switch).
In contrast, the if() statement is general (it can be used to test anything sequentially, including pointers, floating point values). All values being compared with can be variables (not fixed at compile time). It can also be used for more complex boolean expressions (and, or, etc).
Generally, if you are doing an integral comparison, and know all of the values being compared with, then the code will often (subjectively) be more readable and understandable using a switch/case than a lot of if/else/if with boolean expressions. Either way, depending on quality of implementation of the compiler, it can map either construct to the other. I would therefore suggest aiming for code readability than executable size, and allow the compiler (with suitable options, such as to minimimise code size) to sort out the code size issues.
And, if it really matters, measure ensuring you use an appropriate set of compiler and linker options. And bear in mind that the code which produces the "smallest" result for one compiler (and set of compiler options) and host system will not necessarily do the same with another compiler or host system.
Do that too soon, and all you are doing is premature optimisation. Which deserves the social stigma associated with other things that occur prematurely.
Warning: Opinions subject to change without notice
The C Library Reference Guide
Understand the fundamentals
Then have some more fun