4.3.4. Exploiting the C library

If you create an application that includes a main() function, the linker automatically includes the initialization code necessary for the execution environment. See Building an application with the C library for instructions. There are situations though where this is not desirable or possible.

You can create an application that consists of customized startup code and still use many of the library functions. You must either:

Program design

The functions you must re-implement depend on how much of the library functionality you require as follows:

  • If you want only the compiler support functions for division, structure copy, and FP arithmetic, you must provide __rt_raise(). This also enables very simple library functions such as those in errno.h, setjmp.h, and most of string.h to work.

  • If you call setlocale() explicitly, locale-dependent functions start to work. This enables you to use the atoi family, sprintf(), sscanf(), and the functions in ctype.h

  • Programs that use floating-point must call _fp_init(). If you select software floating-point, the program must also provide __rt_fp_status_addr(). (The default action is this function is not reimplemented is to create a user libspace area.

  • Implementing high-level input/output support is necessary for functions that use fprintf() or fputs(). The high-level output functions depend on fputc() and ferror(). The high-level input functions depend on fgetc() and __backspace().

  • Implementing the above functions and the heap enables you to use almost the entire library.

Using low-level functions

If you are using the libraries in an application that does not have a main() function, you must re-implement some functions in the library. See The standalone C library functions for a detailed list of functions that are not available, functions that are available without modification, and functions that are available after other lower-level functions are re-implemented.

__rt_raise() is essential. It is required by all FP functions, by integer division so that divide-by-zero can be reported, and by some other library routines. You probably cannot write a nontrivial program without doing something that requires __rt_raise().


If rand() is called, srand() must be called first. This is done automatically during library initialization but not when you avoid the library initialization.

Using high-level functions

High-level I/O functions, fprintf() for example, can be used if the low-level functions, fputc() for example, are re-implemented. Most of the formatted output functions also require a call to setlocale(). See Tailoring the input/output functions for instructions.

Anything that uses locale must not be called before first calling setlocale() to initialize it, for example call setlocale(LC_ALL, "C"). Locale-using functions are described in The standalone C library functions. These include the functions in ctype.h and locale.h, the printf() family, the scanf() family, ato*, strto*, strcoll/strxfrm, and much of time.h.

Using malloc()

If heap support is required for bare machine C, _init_alloc() must be called first to supply initial heap bounds, and __rt_heap_extend() must be provided even if it only returns failure. Prototypes for both functions are in rt_heap.h.

Copyright © 1999-2001 ARM Limited. All rights reserved.ARM DUI 0067D