Difference between revisions of "C runtime library"

From SEGGER Wiki
Jump to: navigation, search
m
m
Line 38: Line 38:
 
A very simple memcpy implementation would copy bytes in a loop, one byte at a time, and be written in C, looking as below:
 
A very simple memcpy implementation would copy bytes in a loop, one byte at a time, and be written in C, looking as below:
 
<syntaxhighlight lang="c">
 
<syntaxhighlight lang="c">
  +
void memcpy(void *pDest, void *pSrc, int NumBytes) {
 
  +
void *memcpy( void *dest, const void *src, size_t NumBytes) {
  +
char *pDest;
  +
char *pSrc;
  +
  +
pDest = (char*)dest;
  +
pSrc = (char*)src;
  +
 
while (NumBytes > 0) {
 
while (NumBytes > 0) {
 
*pDest++ = *pSrc++;
 
*pDest++ = *pSrc++;

Revision as of 10:00, 22 June 2019

The C runtime library is a collection of routines that 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 programs 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:

  • strcpy
  • memcpy
  • memset
  • strcmp
  • printf
  • snprintf
  • heap functions such as malloc, 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 can not easily be implemented on the given CPU. Typical things are arithmetic routines. On a CPU which does not have a divide instruction, a divide routine has to be provided in the library, so that the code required to perform this division does not need to be inserted everywhere 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 of powerful enough. Modern Compilers implement 64-bit variables, and the 64-bit arithmetic can not be easily 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 a crypto algorithms, and their performance is important to the system performance of these algorithms.

Implementation

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. Thechnically, other languages can be used (such as C++), but typically are not.

Performance

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, looking as below:

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

  pDest = (char*)dest;
  pSrc  = (char*)src;

  while (NumBytes > 0) {
    *pDest++ = *pSrc++;
  }
}

Size of the C runtime library

Granularity

Ideally, the C runtime library has very fine granularity. This means that 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 important especially in Embedded Systems, where a lot of times the application program does not use the heap. If the runtime library needs the heap, than 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.