SONIX MCU C Language Programming Method, for other types of MCU should also have some reference.
Source: Help Document in the C Language Compiler of SONIX Single Chip Microcomputer "SN8 C studio"
1. Do not use the keyword "long" if it is sufficient to define or declare variables as int data types. In the same way, don't use "double" if the float is accurate enough.
2. If a general pointer is declared, when pointers are used in programs, it is necessary to judge whether the pointer points to RAM or ROM. But using the ram / rom pointer can avoid this extra action!
int* pInt;
int g;
void main()
{
pInt = &g1;
g = 1;
if(*pInt != 1)
return 1;
return 0;
}
------------------------
Rom has used : 93 [0x5D] words
__RAM int* pRam;
int g;
int main()
{
pRam = &g;
g = 1;
if(*pRam != 1)
return 1;
return 0;
}
Rom has used : 79 [0x4F] words
3. If a flag has only two states: 0 or 1, the bit data type can be used instead of the int type. Because bit-type operations are simpler than int-type operations, fewer instructions are generated. In addition, bit variables occupy less memory than int variables.
4. Because the operation of multidimensional array is complex, C compiler must generate a large number of instructions to implement multidimensional array operation. So don't use multidimensional arrays.
5. Generally, when using int data types, the C compiler generates instructions to handle negative conditions, but most of these instructions are useless for arrays. So users can use unsigned type to avoid this problem.
int a[10];
int main(void)
{
int i;
for(i = 0;i<=9;i++)
a[i] = 1;
}
Rom has used : 73 [0x49] words
--------------------
int a[10];
int main(void)
{
unsigned i;
for(i = 0;i<=9;i++)
a[i] = 1;
}
Rom has used :70 [0x46] words
6. If the global variable is in ram bank 0, no additional instructions need to be generated to change the RBANK register.
#pragma rambank 1
int g_i, g_j,g_k;
int main(void)
{
int i,j,k;
i = 1;
g_i = 1;
j = 1;
g_j = 1;
k = 1;
g_k = 1;
}
Rom has used : 69 [0x45] words
---------------------
#pragma rambank 0
int g_i, g_j,g_k;
int main(void)
{
int i,j,k;
i = 1;
g_i = 1;
j = 1;
g_j = 1;
k = 1;
g_k = 1;
}
Rom has used : 64 [0x40] words
7. Because the operation of bit data type is simpler than pointer, using bit reference type instead of pointer is a better way to reduce code size.
#include<sn8p2708a.h>
int main(void)
{
if(FP4CON2 != FP4CON3)
return 1;
else
return 0;
}
Rom has used : 76 [0x4C] words
----------------------
#pragma data_address 0xae:2
sbit fpcon2;
#pragma data_address 0xae:3
sbit fpcon3;
int main(void)
{
if(fpcon2 != fpcon3)
return 1;
else
return 0;
}
Rom has used : 62 [0x3E] words
8. Because the operation of bit data type is simpler than that of bit field, using bit reference type instead of bit archiving is a better way to reduce code size. That is to say, direct bit definition does not need to be categorized.
struct BitField
{
unsigned int bit0:1;
unsigned int bit1:1;
unsigned int bit2:1;
unsigned int bit3:1;
unsigned int bit4:1;
unsigned int bit5:1;
unsigned int :2;
};
int main(void)
{
struct BitField bitfield;
bitfield.bit0 = 1;
if(bitfield.bit1==1)
bitfield.bit2 = 0;
if(bitfield.bit3!=0)
bitfield.bit3 = 0;
}
Rom has used : 73 [0x49] words
------------------------
int bitfield;
int main(void)
{
sbit bit0 = bitfield:0;
sbit bit1 = bitfield:1;
sbit bit2 = bitfield:2;
sbit bit3 = bitfield:3;
bit0 = 1;
if(bit1==1)
{
bit2 = 0;
}
if(bit3!=0)
{
bit3 = 0;
}
}
Rom has used : 64 [0x40] words
9. In order to achieve the same function, using variables generates fewer instructions than pointers. So don't use pointers as much as possible.
int main (void)
{
int i;
int *p = &i;
*p= 1;
}
Rom has used : 62 [0x3E] words
--------------------------
int main (void)
{
int i;
int *p = &i;
i = 1;
}
Rom has used : 58 [0x3A] words
10. If pointers are used many times in a program and their values do not change frequently, variables can be used as substitutions to accomplish the same work.
#include<sn8p2708a.h>
int main(void)
{
int temp = R;
int i = 2;
int j = temp*i;
int k = temp*j;
}
Rom has used : 71 [0x47] words
-----------------------
#include<sn8p2708a.h>
int main(void)
{
int i = 2;
int j = R*i;
int k = R*j;
}
Rom has used : 69 [0x45] words
11. When using "++/ -" and other operators together, the compiler first increases the value of the variable before or after the register, and then gets the value of the register to start other operations, so a lot of redundant code will be generated, so it's better to use only "+/-"!
#include<sn8p2708a.h>
int main(void)
{
long i;
if(++i == 10)
i = 0;
}
Rom has used : 74 [0x4A] words
---------------------------
#include<sn8p2708a.h>
int main(void)
{
long i;
i++;
if(i == 10)
i = 0;
}
Rom has used : 64 [0x40] words
12. There is a sequence of multiplication code sizes for each type: unsigned
int main(void)
{
int i1 = 12;
int i2 =i1 * 2.0;
}
Rom has used :472 [0x1D8] words
-------------------------------------
int main(void)
{
int i1 = 12;
int i2 =i1 * 2;
}
Rom has used : 56 [0x38] words
15. Sometimes, if the division results of int and float data types are allocated to int variables, the float data types are converted to int as much as possible to avoid loading the Std library and achieving the same results.
int main(void)
{
int i1 = 12;
int i2 =i1 /3.0;
}
Rom has used : 472 [0x1D8] words
--------------------------
int main(void)
{
int i1 = 12;
int i2 =i1/ 3;
}
Rom has used : 56 [0x38] words
16. Convert the int ant float type to a division related to the int type as far as possible, because the multiplication of int and float is more complex than the division of int type. For example:
int main(void)
{
int i= 2;
int j = i*0.5;
}
Rom has used : 461 [0x1CD] words
----------------------
int main(void)
{
int i= 2;
int j = i/2;
}
Rom has used : 120 [0x78] words
17. Generally, the code size of multiplication is smaller than that of division of the same data type, so as far as possible, the division is converted to multiplication.
int main(void)
{
float i= 2.0;
float j = i/2.0;
}
Rom has used : 418 [0x1A2] words
----------------------------
int main(void)
{
float i= 2.0;
float j = i*0.5;
}
Rom has used : 387 [0x183] words
18. If the result of the assignment of an int variable is given, and the addition of a floating-point type is involved. It's a good suggestion to convert float type to int, because it's useless to use float type here most of the time!
int main(void)
{
int i1 = 12;
int i2 =i1 + 2.0;
}
Rom has used : 472 [0x1D8] words
------------------------------
int main(void)
{
int i1 = 12;
int i2 =i1 + 2;
}
Rom has used : 56 [0x38] words
19. If the result of subtraction is assigned to an int variable, and the addition of floating-point types is involved. There's a good suggestion to hide float types as int, because it's useless to use float types here most of the time!
int main(void)
{
int i1 = 12;
int i2 =i1 – 3.0;
}
Rom has used : 74 [0x4A] words
----------------------------------
int main(void)
{
int i1 = 12;
int i2 =i1 - 3;
}
Rom has used : 71 [0x47] words
20. Generally speaking, the operation of "<" is simpler than that of ", so it is a good idea to adopt"<"instead of".
int main(void)
{
long i = 2;
i = i * 64;
}
Rom has used : 82 [0x52] words
----------------------------------
int main(void)
{
long i = 2;
i = i << 6;
}
Rom has used : 62 [0x3E] words
21. Generally speaking, the operation of ">" is simpler than "/", so replacing "/" with ">" is a good idea to reduce code size.
int main(void)
{
long i = 264;
i = i/64;
}
Rom has used : 183 [0xB7] words
--------------------------
int main(void)
{
int i = 264;
i = i>>6;
}
Rom has used : 65 [0x41] words
22. Generally speaking, the operation of'&'is simpler than'%', so it is a good idea to use'&' instead of'%'to reduce the size of the code.
int main(void)
{
int i = 6;
int j = i%8;
}
Rom has used : 120 [0x78] words
--------------------------------
int main(void)
{
int i = 6;
int j1 = i&7;
}
Rom has used : 56 [0x38] words
23. If the chip does not support MUL instructions, the C compiler will load the Std library to accomplish this task. To avoid this complex operation, it is a better way to use addition as much as possible instead of simple multiplication.
int main(void)
{
int i, j;
i = i * 3;
}
Rom has used : 82 [0x52] words
--------------------------
int main(void)
{
int i, j;
i = i + i + i ;
}
Rom has used : 59 [0x3B] words
24. If compare operates between integer and const, for code size considerations, you can change const to const +1 and use ">=" instead of ">".
int main(void)
{
int i1 = 12;
int i2 = 0;
if(i1 > 10)
i2 = 1;
}
Rom has used : 63 [0x3F] words
------------------------------
int main(void)
{
int i1 = 12;
int i2 = 0;
if(i1 >= 11)
i2 = 1;
}
Rom has used : 61 [0x3D] words
25. If compare operates between integer and const, for code size considerations, you can change const to const + 1 and use "<" instead of "<=".
int main(void)
{
int i1 = 12;
int i2 = 0;
if(i1 <= 10)
i2 = 1;
}
Rom has used : 66 [0x42] words
------------------------------
int main(void)
{
int i1 = 12;
int i2 = 0;
if(i1 < 11)
i2 = 1;
}
Rom has used : 61 [0x3D] words
26. For bit variables, the operation ratio of "" is "!" Simple, so take "" instead of "!" It's a good idea to reduce code size.
int main(void)
{
bit i,j;
i = 0;
j = !i;
if(j == 0)
return 1;
return 0;
}
Rom has used : 82 [0x52] words
--------------------------------
int main(void)
{
bit i,j;
i = 0;
j = ~i;
if(j == 0)
return 1;
return 0;
}
Rom has used : 71 [0x47] words
27. For long expressions, the c compiler generates temporary variables to store the values of subexpressions. We can decompose complex operations into simple sequence of statements.
int main(void)
{
int a;
int b;
int c;
int d, e;
e = (a + b) * c * a + b;
}
Rom has used : 66 [0x42] words
---------------------------
int main(void)
{
int a, b, c, d, e;
e = a + b;
e *= c;
e *= a;
e += b;
}
Rom has used : 60 [0x3C] words
28. For complex if statements, the c compiler generates temporary variables to store the values of some subconditions. We can decompose complex operations into simple sequence of statements.
int main(void)
{
int a,b,c;
if(a == b && b == c && a != c )
;
}
Rom has used : 70 [0x46] words
------------------------------
int main(void)
{
int a,b,c;
if(a==b)
if(b == c)
if(a != c)
;
}
Rom has used : 64 [0x40] words
29. Sometimes, adjusting the framework's "if" statement can reduce code size, such as:
#include<sn8p2708a.h>
int main(void)
{
int i,j;
int flag;
if(flag)
i = 0;
else
i = 1;
}
Rom has used : 59 [0x3B] words
--------------------------------
#include<sn8p2708a.h>
int main(void)
{
int i, j;
int flag;
i = 1;
if (flag)
i = 0;
}
Rom has used : 58 [0x3A] words
30. For c source code, the syntax tree of the conditional expression of the compiler is more complex than that of the "if else" statement, so the compiler can generate fewer instructions to implement the function than the conditional expression of the "if else" statement.
#include<sn8p2708a.h>
int main(void)
{
int i;
i = FP27M ? 1:0;
}
Rom has used : 60 [0x3C] words
------------------------------------
#include<sn8p2708a.h>
int main(void)
{
int i;
if(FP27M) i = 1;
else i = 0;
}
Rom has used : 58 [0x3A] words
31. The compiler can compile and select the correct statement according to the condition, so it is a good way to reduce the code size.
int LETTER = 1;
void main()
{
char str[20]="C Language";
char c;
int i=0;
while(i<=19)
{
c = str[i];
if (LETTER == 1)
if(c>='a'&& c<='z') c=c-32;
else
if(c>='A'&& c<='Z') c=c+32;
str[i] = c;
i++;
}
}
Rom has used : 144 [0x90] words
-------------------------------------------------
#define LETTER 1
void main()
{
char str[20]="C Language";
char c;
int i=0;
while(i<=19)
{
c = str[i];
#if LETTER
if(c>='a'&& c<='z') c=c-32;
#else
if(c>='A'&& c<='Z') c=c+32;
#endif
str[i] = c;
i++;
}
}
Rom has used : 124 [0x7C] words
32. When using multi-tier "if else" statements in programs, it is recommended to use "switch" statements instead of multi-tier ones. If the "switch" statement satisfies the jump table condition, the compiler generates fewer instructions for it.
int main(void)
{
int i, test = 1;
if(test == 0) i = 0;
else if (test == 1)
i = 1;
else if (test == 2)
i = 2;
else if (test == 3)
i = 3;
else if (test == 4)
i = 4;
else if (test == 5)
i = 5;
else if(test == 6)
i = 6;
else if(test ==7)
i = 7;
else if(test == 8)
i = 8;
}
Rom has used : 106 [0x6A] words
---------------------
int main(void)
{
int i; int test = 1;
switch (test) {
case 0: i = 0;
break;
case 1: i = 1;
break;
case 2: i = 2;
break;
case 3: i = 3;
break;
case 4: i = 4;
break;
case 5: i = 5;
break;
case 6: i = 6;
break;
case 7: i = 7;
break;
case 8: i = 8;
break; }
}
Rom has used : 102 [0x66] words
33. If the "switch" statement does not meet the conditions of the jump table, the compiler generates more instructions than if else statements.
void main( )
{
int i = 1;
switch (i){
case 1: i=1;
break;
case 25: i=2;
break;
case 43: i=3;
break;
case 102: i=4;
break;
case -6: i=5;
break; }
}
Rom has used : 106 [0x6A] words
------------------------------
void main()
{
int i = 1;
if (i==1)
i=1;
else if (i==25)
i=2;
else if (i==43)
i=3;
else if (i==102)
i=4;
else if (i==-6)
i=5;
}
Rom has used : 82 [0x52] words
34. Avoid function calls in if / while / for, because function calls in "if / while / for" generate implicit variables
int fun (void)
{
int i = 0;
return i;
}
int main (void)
{
int i;
if(fun() == 0)
i = 0;
else if (fun() == 1)
i = 1;
else if (fun() == 2)
i = 2;
}
Rom has used : 75 [0x4B] words
------------------------
int fun(void)
{
int i = 0;
return i;
}
int main(void)
{
int i, temp = fun();
if (temp== 0)
i = 0;
else if (temp == 1)
i = 1;
else if (temp == 2)
i = 2;
}
Rom has used : 73 [0x49] words
35. When calling other functions in the interrupt function, the compiler needs to generate a set of operations to save and restore the environment in the event of an interrupt. So write code directly in the interrupt function to avoid the compiler doing this tedious work as much as possible!
void fun()
{
__asm
{
MOV A, #0x01
B0MOV RBANK, A;
}
}
__interrupt interruptfun()
{
fun();
}
void main(void)
{
}
Rom has used : 126 [0x7E] words
-------------------
__interrupt interruptfun()
{
__asm
{
MOV A,#0x01
B0MOV RBANK A;
}
}
void main (void)
{
}
Rom has used : 64 [0x40] words
36. If some operations are frequently used in programs, collecting them into a function is a feasible way to reduce code size.
int array[10][10];
int main(void)
{
int i,j;
for(i = 0;i <= 9; i++)
for(j = 0;j<= 9; j++)
array[i][j] = 0;
// do other something
}
int fun(void)
{
int i,j;
for(i = 0;i <= 9; i++)
for(j = 0;j<= 9; j++)
array[i][j] = 0;
// do other something
}
Rom has used : 180 [0xB4] words
------------------------------
int array[10][10];
void init_array(void)
{
int i, j;
for(i = 0;i <= 9; i++)
for(j = 0;j<= 9; j++)
array[i][j] = 0;
}
int main(void)
{
init_array();
// do other something
}
int fun(void)
{
init_array();
// do other something
}
Rom has used : 129 [0x81] words
37. When using parameters in a function, the compiler must first input the parameters into the parameters. Then you use parameters to pass values, but using global variables can avoid this extra action to achieve the same function.
int fun(int g_i,int g_j)
{
int i = g_i;
int j = g_j;
}
int main(void)
{
int i, j;
fun(i, j);
}
Rom has used : 64 [0x40] words
--------------------------------
int g_i, g_j;
int fun (void)
{
int i = g_i;
int j = g_j;
}
int main(void)
{
fun();
}
Rom has used : 60 [0x3C] words
38. Passing the address of a parameter of type struct or union saves more code size. Otherwise, it requires more code size for structured or federated copies.
typedef struct Solstruct
{
int i;
int j;
int k;
int q;
}Sstruct;
void fun(struct Solstruct s)
{
}
int main(void)
{
struct Solstruct s;
fun(s);
}
Rom has used : 66 [0x42] words
-------------------------------
typedef struct Solstruct
{
int i;
int j;
int k;
int q;
}Sstruct;
void fun(struct Solstruct *s)
{
}
int main(void)
{
struct Solstruct s;
fun(&s);
}
Rom has used : 58 [0x3A] words
39. If a function does not need a return value, declare it as a void type, because if the function is not a void type, the compiler generates some code about the return value.
int fun(void)
{
return 1;
}
int main(void)
{
fun();
return 0;
}
Rom has used : 56 [0x38] words
--------------------------------
void fun(void)
{
}
int main(void)
{
fun();
return 0;
}
Rom has used : 54 [0x36] words
40. When using function pointers in programs, they are more complex than functions, so don't use them as much as possible.
void (*funptr)();
void fun(void)
{
}
int main(void)
{
funptr = fun;
funptr();
}
Rom has used : 82 [0x52] words
-----------------------------
void (*funptr)();
void fun(void)
{
}
int main(void)
{
funptr = fun;
fun();
}
Rom has used : 58 [0x3A] words
41. For example, instructions on multidimensional arrays generated by compilers are complex and redundant, so we can use inline assemblers!
#include<sn8p2708a.h>
int a[5][5];
int main (void)
{
int i, j;
for(i=0;i<=4;i++)
{
for(j=0;j<=4;j++)
{
a[i][j] = 1;
}
}
}
Rom has used : 128 [0x80] words
-------------------------------
#include<sn8p2708a.h>
int a[5][5];
int main(void)
{
int i,j;
for(i=0;i<=4;i++)
{
for(j=0;j<=4;j++)
{
__asm{
SelectBank(i)
MOV A, #5
MUL A,CNameToAsmLabel(i)
SelectBank(j)
ADD A,CNameToAsmLabel(j)
ADD A, #(CNameToAsmLabel(a))$L
B0MOV Z,A;
MOV A, #(CNameToAsmLabel(a))$M
B0MOV Y,A
MOV A,#0x01
B0MOV @YZ, A}
}
}
}
Rom has used : 81 [0x51] words
42. Good arithmetic is more effective than a good compiler!
void BubbleSort(int* pData,int Count)
{
int iTemp;
int i,j;
for(i=1;i<Count;i++)
{
for(j=Count-1;j>=i;j--)
{
if(pData[j]<pData[j-1])
{
iTemp = pData[j-1];
pData[j-1] = pData[j];
pData[j] = iTemp;
}
}
}
}
void main()
{
int data[] = {10,9,8,7,6,5,4};
BubbleSort(data,7);
}
Rom has used : 272 [0x110] words
---------------------------
void InsertSort(int* pData,int Count)
{
int iTemp;
int iPos;
int i;
for(i=1;i<Count;i++)
{
iTemp = pData[i];
iPos = i-1;
while((iPos>=0) && (iTemp<pData[iPos]))
{
pData[iPos+1] = pData[iPos];
iPos--;
}
pData[iPos+1] = iTemp;
}
}
void main()
{
int data[] = {10,9,8,7,6,5,4};
InsertSort(data,7);
}
Rom has used : 241 [0xF1] words