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?
Printable View
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.
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.
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.
Attachment 12384
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
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.
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.
oh. so should i declare it as a global?
You don't need it in any other function, and global variables are bad. Leave it local but make it static. It will live like a global variable (whole program execution lifespan, initialized only once), but it will remain private to its function.
You are using MPLAB from memory -> But you still haven't told us what compiler you are using!
It would also depend on whether you are using the LITE/Standard/PRO (You pay more money, your code gets optimised more)
The best way would be to actually see what is being generated -> The switch statement is usually better when programming your PIC, because it generates an optimised branching table.
Do the two different ways in your code. Click "View" -> "Disassembly listing"
I'm using the C18 compiler PRO -
Code:280: if (test_data == 1)
039AE 0102 MOVLB 0x2
039B0 0E01 MOVLW 0x1
039B2 19FE XORWF 0xfe, W, BANKED
039B4 E101 BNZ 0x39b8
039B6 51FF MOVF 0xff, W, BANKED
039B8 E10C BNZ 0x39d2
281: {
282: puts("1");
039BA 0E76 MOVLW 0x76
039BC 6EE6 MOVWF 0xfe6, ACCESS
039BE 0E4E MOVLW 0x4e
039C0 6EE6 MOVWF 0xfe6, ACCESS
039C2 0E00 MOVLW 0
039C4 6EE6 MOVWF 0xfe6, ACCESS
039C6 ECFA CALL 0x53f4, 0
039C8 F029 NOP
039CA 52E5 MOVF 0xfe5, F, ACCESS
039CC 52E5 MOVF 0xfe5, F, ACCESS
039CE 52E5 MOVF 0xfe5, F, ACCESS
283: }
284: else if (test_data == 2)
039D0 D04F BRA 0x3a70
039D2 0E02 MOVLW 0x2
039D4 19FE XORWF 0xfe, W, BANKED
039D6 E101 BNZ 0x39da
039D8 51FF MOVF 0xff, W, BANKED
039DA E10C BNZ 0x39f4
285: {
286: puts("2");
039DC 0E74 MOVLW 0x74
039DE 6EE6 MOVWF 0xfe6, ACCESS
039E0 0E4E MOVLW 0x4e
039E2 6EE6 MOVWF 0xfe6, ACCESS
039E4 0E00 MOVLW 0
039E6 6EE6 MOVWF 0xfe6, ACCESS
039E8 ECFA CALL 0x53f4, 0
039EA F029 NOP
039EC 52E5 MOVF 0xfe5, F, ACCESS
039EE 52E5 MOVF 0xfe5, F, ACCESS
039F0 52E5 MOVF 0xfe5, F, ACCESS
287: }
288: else if (test_data == 3)
039F2 D03E BRA 0x3a70
039F4 0E03 MOVLW 0x3
039F6 19FE XORWF 0xfe, W, BANKED
039F8 E101 BNZ 0x39fc
039FA 51FF MOVF 0xff, W, BANKED
039FC E10C BNZ 0x3a16
289: {
290: puts("3");
039FE 0E72 MOVLW 0x72
03A00 6EE6 MOVWF 0xfe6, ACCESS
03A02 0E4E MOVLW 0x4e
03A04 6EE6 MOVWF 0xfe6, ACCESS
03A06 0E00 MOVLW 0
03A08 6EE6 MOVWF 0xfe6, ACCESS
03A0A ECFA CALL 0x53f4, 0
03A0C F029 NOP
03A0E 52E5 MOVF 0xfe5, F, ACCESS
03A10 52E5 MOVF 0xfe5, F, ACCESS
03A12 52E5 MOVF 0xfe5, F, ACCESS
291: }
292: else if (test_data == 4)
03A14 D02D BRA 0x3a70
03A16 0E04 MOVLW 0x4
03A18 19FE XORWF 0xfe, W, BANKED
03A1A E101 BNZ 0x3a1e
03A1C 51FF MOVF 0xff, W, BANKED
03A1E E10C BNZ 0x3a38
293: {
294: puts("4");
03A20 0E70 MOVLW 0x70
03A22 6EE6 MOVWF 0xfe6, ACCESS
03A24 0E4E MOVLW 0x4e
03A26 6EE6 MOVWF 0xfe6, ACCESS
03A28 0E00 MOVLW 0
03A2A 6EE6 MOVWF 0xfe6, ACCESS
03A2C ECFA CALL 0x53f4, 0
03A2E F029 NOP
03A30 52E5 MOVF 0xfe5, F, ACCESS
03A32 52E5 MOVF 0xfe5, F, ACCESS
03A34 52E5 MOVF 0xfe5, F, ACCESS
295: }
296: else if (test_data == 5)
03A36 D01C BRA 0x3a70
03A38 0E05 MOVLW 0x5
03A3A 19FE XORWF 0xfe, W, BANKED
03A3C E101 BNZ 0x3a40
03A3E 51FF MOVF 0xff, W, BANKED
03A40 E10C BNZ 0x3a5a
297: {
298: puts("5");
03A42 0E6E MOVLW 0x6e
03A44 6EE6 MOVWF 0xfe6, ACCESS
03A46 0E4E MOVLW 0x4e
03A48 6EE6 MOVWF 0xfe6, ACCESS
03A4A 0E00 MOVLW 0
03A4C 6EE6 MOVWF 0xfe6, ACCESS
03A4E ECFA CALL 0x53f4, 0
03A50 F029 NOP
03A52 52E5 MOVF 0xfe5, F, ACCESS
03A54 52E5 MOVF 0xfe5, F, ACCESS
03A56 52E5 MOVF 0xfe5, F, ACCESS
299: }
300: else
03A58 D00B BRA 0x3a70
301: {
302: puts("?");
03A5A 0E6C MOVLW 0x6c
03A5C 6EE6 MOVWF 0xfe6, ACCESS
03A5E 0E4E MOVLW 0x4e
03A60 6EE6 MOVWF 0xfe6, ACCESS
03A62 0E00 MOVLW 0
03A64 6EE6 MOVWF 0xfe6, ACCESS
03A66 ECFA CALL 0x53f4, 0
03A68 F029 NOP
03A6A 52E5 MOVF 0xfe5, F, ACCESS
03A6C 52E5 MOVF 0xfe5, F, ACCESS
03A6E 52E5 MOVF 0xfe5, F, ACCESS
303: }
304:
305: switch (test_data)
03A70 0E05 MOVLW 0x5
03A72 0102 MOVLB 0x2
03A74 19FE XORWF 0xfe, W, BANKED
03A76 E101 BNZ 0x3a7a
03A78 51FF MOVF 0xff, W, BANKED
03A7A E045 BZ 0x3b06
03A7C 0E04 MOVLW 0x4
03A7E 19FE XORWF 0xfe, W, BANKED
03A80 E101 BNZ 0x3a84
03A82 51FF MOVF 0xff, W, BANKED
03A84 E034 BZ 0x3aee
03A86 0E03 MOVLW 0x3
03A88 19FE XORWF 0xfe, W, BANKED
03A8A E101 BNZ 0x3a8e
03A8C 51FF MOVF 0xff, W, BANKED
03A8E E023 BZ 0x3ad6
03A90 0E02 MOVLW 0x2
03A92 19FE XORWF 0xfe, W, BANKED
03A94 E101 BNZ 0x3a98
03A96 51FF MOVF 0xff, W, BANKED
03A98 E012 BZ 0x3abe
03A9A 0E01 MOVLW 0x1
03A9C 19FE XORWF 0xfe, W, BANKED
03A9E E101 BNZ 0x3aa2
03AA0 51FF MOVF 0xff, W, BANKED
03AA2 E001 BZ 0x3aa6
03AA4 D03C BRA 0x3b1e
306: {
307: case 1:
308: puts("1");
03AA6 0E76 MOVLW 0x76
03AA8 6EE6 MOVWF 0xfe6, ACCESS
03AAA 0E4E MOVLW 0x4e
03AAC 6EE6 MOVWF 0xfe6, ACCESS
03AAE 0E00 MOVLW 0
03AB0 6EE6 MOVWF 0xfe6, ACCESS
03AB2 ECFA CALL 0x53f4, 0
03AB4 F029 NOP
03AB6 52E5 MOVF 0xfe5, F, ACCESS
03AB8 52E5 MOVF 0xfe5, F, ACCESS
03ABA 52E5 MOVF 0xfe5, F, ACCESS
309: break;
03ABC D03B BRA 0x3b34
310:
311: case 2:
312: puts("2");
03ABE 0E74 MOVLW 0x74
03AC0 6EE6 MOVWF 0xfe6, ACCESS
03AC2 0E4E MOVLW 0x4e
03AC4 6EE6 MOVWF 0xfe6, ACCESS
03AC6 0E00 MOVLW 0
03AC8 6EE6 MOVWF 0xfe6, ACCESS
03ACA ECFA CALL 0x53f4, 0
03ACC F029 NOP
03ACE 52E5 MOVF 0xfe5, F, ACCESS
03AD0 52E5 MOVF 0xfe5, F, ACCESS
03AD2 52E5 MOVF 0xfe5, F, ACCESS
313: break;
03AD4 D02F BRA 0x3b34
314:
315: case 3:
316: puts("3");
03AD6 0E72 MOVLW 0x72
03AD8 6EE6 MOVWF 0xfe6, ACCESS
03ADA 0E4E MOVLW 0x4e
03ADC 6EE6 MOVWF 0xfe6, ACCESS
03ADE 0E00 MOVLW 0
03AE0 6EE6 MOVWF 0xfe6, ACCESS
03AE2 ECFA CALL 0x53f4, 0
03AE4 F029 NOP
03AE6 52E5 MOVF 0xfe5, F, ACCESS
03AE8 52E5 MOVF 0xfe5, F, ACCESS
03AEA 52E5 MOVF 0xfe5, F, ACCESS
317: break;
03AEC D023 BRA 0x3b34
318:
319: case 4:
320: puts("4");
03AEE 0E70 MOVLW 0x70
03AF0 6EE6 MOVWF 0xfe6, ACCESS
03AF2 0E4E MOVLW 0x4e
03AF4 6EE6 MOVWF 0xfe6, ACCESS
03AF6 0E00 MOVLW 0
03AF8 6EE6 MOVWF 0xfe6, ACCESS
03AFA ECFA CALL 0x53f4, 0
03AFC F029 NOP
03AFE 52E5 MOVF 0xfe5, F, ACCESS
03B00 52E5 MOVF 0xfe5, F, ACCESS
03B02 52E5 MOVF 0xfe5, F, ACCESS
321: break;
03B04 D017 BRA 0x3b34
322:
323: case 5:
324: puts("5");
03B06 0E6E MOVLW 0x6e
03B08 6EE6 MOVWF 0xfe6, ACCESS
03B0A 0E4E MOVLW 0x4e
03B0C 6EE6 MOVWF 0xfe6, ACCESS
03B0E 0E00 MOVLW 0
03B10 6EE6 MOVWF 0xfe6, ACCESS
03B12 ECFA CALL 0x53f4, 0
03B14 F029 NOP
03B16 52E5 MOVF 0xfe5, F, ACCESS
03B18 52E5 MOVF 0xfe5, F, ACCESS
03B1A 52E5 MOVF 0xfe5, F, ACCESS
325: break;
03B1C D00B BRA 0x3b34
326:
327: default:
328: puts("?");
03B1E 0E6C MOVLW 0x6c
03B20 6EE6 MOVWF 0xfe6, ACCESS
03B22 0E4E MOVLW 0x4e
03B24 6EE6 MOVWF 0xfe6, ACCESS
03B26 0E00 MOVLW 0
03B28 6EE6 MOVWF 0xfe6, ACCESS
03B2A ECFA CALL 0x53f4, 0
03B2C F029 NOP
03B2E 52E5 MOVF 0xfe5, F, ACCESS
03B30 52E5 MOVF 0xfe5, F, ACCESS
03B32 52E5 MOVF 0xfe5, F, ACCESS
329: }