I'm new to embedded C development and I'm looking for some general principals/guidelines for managing the size of the generated code.

In my specific example I'm using XC8 on a PIC18F4550. My code so far uses about 13% of the space. Once I use "time.h" and 1/2 functions from it, the usage jumps to 45%! I realise that the free XC8 compiler does not optimise but I'm still very surprised to see just how much space is used.

What I'm looking for a tips / staring points along the lines of

  • Alternatives to the standard libraries that implement on small targeted subsets of the functionality. E.g. a date/time lib. i.e. are there repositions I can get useful routines from?
  • How to see what is using all the space. (Listing/map files - and tips for analysing them)
  • Any other tips / resources.

EDIT: I found a nice implementation without using stdlib here: https://codereview.stackexchange.com/questions/38275/convert-between-date-time-and-time-stamp-without-using-std-library-routines

The general question still stands though. Are there guidelines, good repository sources etc

  • \$\begingroup\$ Isn't opt level 1 allowed? For little more you can get one of the newish pic32 line with much more flash. It seems that xc8 is more limited than the 16 and 32 compilers. \$\endgroup\$ Commented May 16, 2014 at 15:18
  • 1
    \$\begingroup\$ @ErikFriesen Thanks I'll definitely try the pic32 range later on. For now I want to try get it to work with the pic18. I'm also interested in this in a general way though. I.e. there will always be some space restriction and I'd like to understand ways to improve things \$\endgroup\$
    – Andre
    Commented May 16, 2014 at 16:03
  • 1
    \$\begingroup\$ We have one license of XC8 pro that our main firmware guy uses. The rest of us develop with the free version for smaller stuff, and he pulls and compiles if necessary for optimization. It seems to me that the compiler applies all the optimization in the free version, but inserts a bunch of branch instructions. So the disassembly from the pro and free versions looks the same, the free version just has a whole bunch of branches jumping around. You could take whatever functionality you need from the time library, and spin your own. There is almost always space savings to be had there. \$\endgroup\$
    – Matt Young
    Commented May 16, 2014 at 16:24
  • \$\begingroup\$ Thanks @MattYoung, yeah I think the answer for the libraries is going to pretty much be just google for existing solutions / other stdlibs and modify from there. It seems that the space savings will be significant. I'm surprised that there are not more differences between the free and pro outputs. I have seen lots of comments/complaints to the contrary. Very interesting. \$\endgroup\$
    – Andre
    Commented May 16, 2014 at 16:36
  • \$\begingroup\$ I've only extensively compared the two in a couple of applications where timing was critical, but those were my findings. It would definitely be worth reading into further. \$\endgroup\$
    – Matt Young
    Commented May 16, 2014 at 16:39

3 Answers 3


Here are some things I have done when using Microchips C18 compiler. Maybe the concepts will apply to your compiler: - declare each string one time. Put in a separate .c file and use a .h file to reference them. In other words don't duplicate display messages multiple times. - declare strings so that they go in rom. This wont help you with ROM (code space) but it will save memory. - write tight code. If several lines of code are duplicated, put them in a function. Copy / paste is not necessary an embedded programmers best friend. - like you already thought of, implement your own functions instead of including a library. I once saved a ton of space by creating my own itoa() function. Try not to use printf.


I've done some looking around and here are the tips I can find

  1. Write better code. Code size and speed must be considered at each step of the way.
  2. C compiler/linker will only use the functions you actually use. So just including a .h should not increase code size (much)
  3. Standard functions are however often more generic than you require. It is possible to write smaller versions that only do what you required
  4. Shared strings as per @BrianK's answer

Then there are some alternatives that don't address the core issue of code size but may need to be considered if all else fails

  1. Use a PIC with more space
  2. Use an optimising compiler, e.g. MPLAB Pro
  3. Use assembler for some or all of the code

I would still like an easy way of seeing which functions and included functions are using the most space. I'll update here if I find an easy way to do so.


Implementing your own version of standard functions instead of including the entire library can help. There are a million smaller, more specific optimizations that you can do, but a good reference collection of those kinds of tricks is the book Hacker's Delight. It's very practical (especially for bit twiddling like you often do on a microcontroller) and I recommend it.

  • 2
    \$\begingroup\$ I have the first edition of Hacker's Delight (and love it). Any ideas what the differences are in the second edition? Is it worth getting if I have the first one? \$\endgroup\$
    – tcrosley
    Commented May 16, 2014 at 17:44
  • \$\begingroup\$ I don't have the first edition, but I believe the second edition adds a bunch of new material as well as some refinements of the original. \$\endgroup\$
    – aloishis89
    Commented May 18, 2014 at 15:26
  • \$\begingroup\$ There is no such thing as "including the entire library", only the functions you use will get linked to the program. Keep in mind that the std library for your compiler is perhaps optimized for the specific target. It seems unlikely that writing your own version of those functions will save space. More likely it will do the opposite. \$\endgroup\$
    – Lundin
    Commented May 20, 2014 at 6:37
  • 2
    \$\begingroup\$ @Lundin that is true. I.e when I use strfmttime I see a large increase in size over just using gmtime etc. However I don't agree with the general statement that writing your own libs wont help. It is unlikely that I can create a more efficient feature for feature replacement. However I only need a small percentage of the functionality provided. (Timezone etc code is included as the gmtime etc assume that). I was able to write a small targeted sub-set of the functionality and save 20% of the space usage. So writing a minimal sub-set is feasible. Good point about linking though. Thanks \$\endgroup\$
    – Andre
    Commented May 20, 2014 at 8:06

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.