How Can I Make My Code Smaller?

There are a number of ways that this can be done, but results vary from one project to the next. Use the assembly list file (see Assembly List Files) to observe the assembly code, produced by the compiler, to verify that the following tips are relevant to your code.

Use the smallest data types possible, as less code is needed to access these (this also reduces RAM usage). Note that a bit type and non-standard 24-bit integer type exists for this compiler. Avoid multi-bit bit-fields whenever possible. The code used to access these can be very large. See Supported Data Types and Variables for all data types and sizes.

There are two sizes of floating-point type, with these being discussed in the same section as well. Avoid floating-point if at all possible. Consider writing fixed-point arithmetic code.

Use unsigned types, if possible, instead of signed types; particularly if they are used in expressions with a mix of types and sizes. Try to avoid an operator acting on operands with mixed sizes whenever possible.

Whenever you have a loop or condition code, use a “strong” stop condition, i.e., the following:

for(i=0; i!=10; i++)

is preferable to:

for(i=0; i<10; i++)

A check for equality (== or !=) is usually more efficient to implement than the weaker < comparison.

In some situations, using a loop counter that decrements to zero is more efficient than one that starts at zero and counts up by the same number of iterations. This is more likely to be the case if the loop index is a byte-wide type. So you might be able to rewrite the above as:

for(i=10; i!=0; i--)

There might be a small advantage in changing the order of function parameters so that the first parameter is byte sized. A register is used if the first parameter is byte-sized. For example consider:

char calc(char mode, int value);

over

char calc(int value, char mode);

Ensure that all optimizations are enabled (see Options for Controlling Optimization). Be aware of what optimizations the compiler performs (see Optimizations and Assembly-Level Optimizations) so you can take advantage of them and don’t waste your time manually performing optimizations in C code that the compiler already handles, e.g., don’t turn a multiply-by-4 operation into a shift-by-2 operation as this sort of optimization is already detected.