C runtime library

From SEGGER Wiki
Revision as of 15:11, 3 July 2019 by MartinBaldwin (talk | contribs) (Implementations of the C runtime library)
Jump to: navigation, search

The C runtime library is a collection of subroutines that are needed to build a program in C. The subroutines can basically be put into 2 categories:

  • C standard library
  • Compiler-specific auxiliary functions

It goes hand in hand with the startup code, which contains the first instructions to be executed when program execution starts. A C runtime library is required equally for Embedded Systems, where the entire program is typically monolithic, so one single executable, as well as for larger systems such as Windows, Linux, MacOS, where the application runs on top of an Operating Systems and typically also in virtual memory space.

Content of C runtime library

C standard library

The functions available in the C standard library are defined in the C-standard. Examples are:

  • memory and string functions, e.g. strcpy, memcpy, memset, strcmp.
  • formatted I/O functions, e.g. printf, snprintf, scanf, sscanf.
  • heap functions, e.g. alloc, free, realloc.

Compiler-specific auxiliary functions

The compiler specific auxiliary functions are highly dependent on compiler and architecture. They typically supply functionality required by the C standard, which cannot easily be implemented using single instructions on the target CPU. Typical things are arithmetic routines. On a CPU which does not offer a divide instruction, a divide routine must be provided in the library, so that the code required to perform this division does not need to be inserted inline where division is required, as the division code might be quite large. Even where a processor has built-in multiplication and division instructions, they are often not powerful enough. Modern Compilers implement 64-bit variables, and the 64-bit arithmetic cannot easily be performed by the processor in a single instruction. Auxiliary functions for 64-bit arithmetic, especially multiplication and division, are required. These functions are actually used by cryptography algorithms, and their performance is important to the system performance of these algorithms.


A C runtime library can be implemented entirely in C (as high level language), but good implementations usually have various routines implemented in Assembly language (ASM) for performance reasons. Technically, other languages can be used (such as C++), but typically are not.


The performance of the application program does depend a lot on the C runtime library. Functions such as memcpy are used a lot by application programs, either directly (visible to the programmers, the application program directly calling memcpy) or even indirectly (by code generated by the compiler, for example to copy a structure). Other functions, such as arithmetic functions, may also have a significant effect on the performance. Different implementations can have vastly different performance, with a difference of factor 10 or more. A very simple memcpy implementation would copy bytes in a loop, one byte at a time, and be written in C, as below:

void *memcpy( void *dest, const void *src, size_t NumBytes) {
  char *pDest;
  char *pSrc;

  pDest = (char*)dest;  // Copy to byte size pointers to make the loop look prettier. Note that most compilers optimize things away anyhow
  pSrc  = (char*)src;

  while (NumBytes > 0) {
    *pDest++ = *pSrc++;
  return dest;          // Actually a waste of time to return the original pointer but it seems that is what the C-standard demands

A good implementation is done in assembly language, will load and store as many words as possible words (so typically 32 bits on a 32-bit processor), and use special instructions where possible and available, such a multi-word read and write. The resulting difference in performance can be huge, and since a lot of applications use memcpy heavily, the difference in performance can be equally huge.

Size of the C runtime library

The size of the C runtime library is basically irrelevant. What is important is how much of it gets linked into the application. And this is where good and not so good implementations vary. A good implementation will add minimum space (for small applications, that can and should be no more than a few hundred bytes), where other implementations will not allow building applications below 20KB.


Ideally, the C runtime library has very fine granularity. This means that only the functions actually referenced by the application are linked into the application.

Use of heap

Good runtime libraries do not require a heap. This is especially important in Embedded Systems, where a lot of times the application program does not use the heap. If the runtime library needs the heap, then the heap is required just for the run time library. This involves linking in the additional code for the heap management of the run time library, as well as setting aside some RAM to be used as heap.

Implementations of the C runtime library

There are lots of implementations available. Basically, every compiler comes with its own implementation, as it is not really fully usable without it. For GCC, various free ones are available, such as glibc, newlib and newlib-nano. There is also a commercial version available, with much better performance and smaller memory footprint: https://wiki.segger.com/SEGGER_RunTime_Library For detailed information visit the SEGGER Runtime Library product page on segger.com.