Again i am slow in updating this blog and this time it is really because I was busy with some GUI building activity on Matlab. I will write more about in another post. However, today the topic is more about "C" coding myths.
Some dudes I have met write really write complicated code like the one below stating that it will be more efficient. Some how they seem to feel that compact code ( in terms of number of lines & characters used) translates directly into lesser code volume in the microcontroller. I just tried this....
Code:
Thus, we break a myth that complicated & compressed "C" files give compressed code. More often that not modern compilers are clever enough to do everything that is needed for optimisation. So please spare yourself the troubel and let the compiler do its job.
However, that doesn't mean that we should write inefficient code. What it means is that - "Dont think you have optimized the code by just changing some "if" statements to "ternary" operators. It is more than that and quite usually compiler dependent". The best way to optimize is to read the compiler manual and try to understand the compiler and its capability. Then you can use tricks in "C" to optimize the code.
Some dudes I have met write really write complicated code like the one below stating that it will be more efficient. Some how they seem to feel that compact code ( in terms of number of lines & characters used) translates directly into lesser code volume in the microcontroller. I just tried this....
Code:
unsigned char alt2(void)
{
unsigned char var=10;
unsigned char output;
if(var==1)
output=3;
else if(var==2)
output = 2;
else
output =1;
return output;
}
unsigned char Alt(void)
{
unsigned char var= 10;
unsigned char output;
output = (var==1)?(3):((var==2)?(2):(1));
return output;
}
void main(void)
{
int x;
x = alt();
x = alt2();
}
Now on compiling this with avr-gcc with -S option you should be able to get the assembly code output also. Let us compare the functions Alt and Alt2 which have same functionalities.
alt2:
push r29
push r28
rcall .
in r28,__SP_L__
in r29,__SP_H__
/* prologue: function */
/* frame size = 2 */
ldi r24,lo8(10)
std Y+2,r24
ldd r24,Y+2
cpi r24,lo8(1)
brne .L2
ldi r24,lo8(3)
std Y+1,r24
rjmp .L3
.L2:
ldd r24,Y+2
cpi r24,lo8(2)
brne .L4
ldi r24,lo8(2)
std Y+1,r24
rjmp .L3
.L4:
ldi r24,lo8(1)
std Y+1,r24
.L3:
ldd r24,Y+1
/* epilogue start */
Alt2 takes a stack frame of 2 bytes and the code is readable to a great extent. I am sure it is more maintainable compared to Alt. However, Alt generates a stack frame of 4 bytes.
Alt:
push r29
push r28
rcall .
rcall .
in r28,__SP_L__
in r29,__SP_H__
/* prologue: function */
/* frame size = 4 */
ldi r24,lo8(10)
std Y+2,r24
ldd r24,Y+2
cpi r24,lo8(1)
breq .L7
ldd r24,Y+2
cpi r24,lo8(2)
brne .L8
ldi r24,lo8(2)
std Y+3,r24
rjmp .L9
.L8:
ldi r24,lo8(1)
std Y+3,r24
.L9:
ldd r24,Y+3
std Y+4,r24
rjmp .L10
.L7:
ldi r24,lo8(3)
std Y+4,r24
.L10:
ldd r24,Y+4
std Y+1,r24
ldd r24,Y+1
We see that now the stack frame is 4 bytes & to add to the woes the code is not so much readable as well. {
unsigned char var=10;
unsigned char output;
if(var==1)
output=3;
else if(var==2)
output = 2;
else
output =1;
return output;
}
unsigned char Alt(void)
{
unsigned char var= 10;
unsigned char output;
output = (var==1)?(3):((var==2)?(2):(1));
return output;
}
void main(void)
{
int x;
x = alt();
x = alt2();
}
Now on compiling this with avr-gcc with -S option you should be able to get the assembly code output also. Let us compare the functions Alt and Alt2 which have same functionalities.
alt2:
push r29
push r28
rcall .
in r28,__SP_L__
in r29,__SP_H__
/* prologue: function */
/* frame size = 2 */
ldi r24,lo8(10)
std Y+2,r24
ldd r24,Y+2
cpi r24,lo8(1)
brne .L2
ldi r24,lo8(3)
std Y+1,r24
rjmp .L3
.L2:
ldd r24,Y+2
cpi r24,lo8(2)
brne .L4
ldi r24,lo8(2)
std Y+1,r24
rjmp .L3
.L4:
ldi r24,lo8(1)
std Y+1,r24
.L3:
ldd r24,Y+1
/* epilogue start */
Alt2 takes a stack frame of 2 bytes and the code is readable to a great extent. I am sure it is more maintainable compared to Alt. However, Alt generates a stack frame of 4 bytes.
Alt:
push r29
push r28
rcall .
rcall .
in r28,__SP_L__
in r29,__SP_H__
/* prologue: function */
/* frame size = 4 */
ldi r24,lo8(10)
std Y+2,r24
ldd r24,Y+2
cpi r24,lo8(1)
breq .L7
ldd r24,Y+2
cpi r24,lo8(2)
brne .L8
ldi r24,lo8(2)
std Y+3,r24
rjmp .L9
.L8:
ldi r24,lo8(1)
std Y+3,r24
.L9:
ldd r24,Y+3
std Y+4,r24
rjmp .L10
.L7:
ldi r24,lo8(3)
std Y+4,r24
.L10:
ldd r24,Y+4
std Y+1,r24
ldd r24,Y+1
Thus, we break a myth that complicated & compressed "C" files give compressed code. More often that not modern compilers are clever enough to do everything that is needed for optimisation. So please spare yourself the troubel and let the compiler do its job.
However, that doesn't mean that we should write inefficient code. What it means is that - "Dont think you have optimized the code by just changing some "if" statements to "ternary" operators. It is more than that and quite usually compiler dependent". The best way to optimize is to read the compiler manual and try to understand the compiler and its capability. Then you can use tricks in "C" to optimize the code.
Powered by ScribeFire.
No comments:
Post a Comment