From ab86dda9cc66a946d257ecb96cbf8a17662af045 Mon Sep 17 00:00:00 2001 From: Andreas Baumann Date: Mon, 30 Mar 2009 21:15:37 +0200 Subject: added C inline docu --- docs/port/inline.txt | 206 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 206 insertions(+) create mode 100644 docs/port/inline.txt (limited to 'docs') diff --git a/docs/port/inline.txt b/docs/port/inline.txt new file mode 100644 index 0000000..7396271 --- /dev/null +++ b/docs/port/inline.txt @@ -0,0 +1,206 @@ + Inline Functions In C + +Introduction + + GNU C (and some other compilers) had inline functions long before + standard C introduced them (in the 1999 standard); this page summarizes + the rules they use, and makes some suggestions as to how to actually + use inline functions. + + The point of making a function "inline" is to hint to the compiler that + it is worth making some form of extra effort to call the function + faster than it would otherwise - generally by substituting the code of + the function into its caller. As well as eliminating the need for a + call and return sequence, it might allow the compiler to perform + certain optimizations between the bodies of both functions. + + Sometimes it is necessary for the compiler to emit a stand-alone copy + of the object code for a function even though it is an inline function + - for instance if it is necessary to take the address of the function, + or if it can't be inlined in some particular context, or (perhaps) if + optimization has been turned off. (And of course, if you use a compiler + that doesn't understand "inline", you'll need a stand-alone copy of the + object code so that all the calls actually work at all.) + + There are various ways to define inline functions; any given kind of + definition might definitely emit stand-alone object code, definitely + not emit stand-alone object code, or only emit stand-alone object code + if it is known to be needed. Sometimes this can lead to duplication of + object code, which is a potential problem for following reasons: + 1. It wastes space. + 2. It can cause pointers to what is apparently the same function to + compare not equal to one another. + 3. It might reduce the effectiveness of the instruction cache. + (Although inlining might do that in other ways too.) + + If any of these are a problem for you then you will want to use a + strategy that avoids duplication. These are discussed below. + +GNU C inline rules + + The GNU C rules are described in the GNU C manual, which is included + with the compiler. This is freely available if you follow links from + e.g. [1]http://gcc.gnu.org. + * A function defined with "inline" on its own. Stand-alone object + code is always emitted. You can only write one definition like this + in your entire program. If you want to use it from other + translation units to the one where it is defined, you put a + declaration in a header file; but it would not be inlined in those + translation units. + This is of rather limited use: if you only want to use the function + from one translation unit then "static inline" below makes more + sense, if not the you probably want some form that allows the + function to be inlined in more than one translation unit. + However it does have the advantage that by defining away the + "inline" keyword, the program reduces to a portable program with + the same meaning (provided no other non-portable constructions are + used). + * A function defined with "extern inline". Stand-alone object code is + never emitted. You can have multiple such definitions and your + program will still work. However, you should add a non-inline + definition somewhere too, in case the function is not inlined + everywhere. + This provides sensible semantics (you can avoid duplicate copies of + the functions' object code) but is a bit inconvenient to use. + One approach to using this would be to put the definitions in a + header file, surrounded by a #if that expands to true either when + using GNU C, or when the header has been included from the file + that is contain the emitted definitions (whether or not using GNU + C). In the latter case the "extern" is omitted (for instance + writing "EXTERN" and #define-ing that to either "extern" or + nothing). The "#else" branch would contain just declarations of the + functions, for non-GNU compilers. + * A function defined with "static inline". Stand-alone object code + may be emitted if required. You can have multiple definitions in + your program, in different translation units, and it will still + work. Just dropping the "inline" reduces the program to a portable + one (again, all other things being equal). + This is probably useful primarily for small functions that you + might otherwise use macros for. If the function isn't always + inlined then you get duplicate copies of the object code, with the + problems described above. + A sensible approach would be to put the "static inline" functions + in either a header file if they are to be widely used or just in + the source files that use them if they are only ever used from one + file. + +C99 inline rules + + The specification for "inline" is section 6.7.4 of the C99 standard + (ISO/IEC 9899:1999). This isn't freely available, but you can buy a PDF + of it from [2]ISO relatively cheaply. + * A function where all the declarations (including the definition) + mention "inline" and never "extern". There must be a definition in + the same translation unit. No stand-alone object code is emitted. + You can (must?) have a separate (not inline) definition in another + translation unit, and the compiler might choose either that or the + inline definition. + Such functions may not contain modifiable static variables, and may + not refer to static variables or functions elsewhere in the source + file where they are declared. + * A function where at least one declaration mentions "inline", but + where some declaration doesn't mention "inline" or does mention + "extern". There must be a definition in the same translation unit. + Stand-alone object code is emitted (just like a normal function) + and can be called from other translation units in your program. + The same constraint about statics above applies here, too. + * A function defined "static inline". A local definition may be + emitted if required. You can have multiple definitions in your + program, in different translation units, and it will still work. + This is the same as the GNU C rules. + + main is not allowed to be an inline function. + + (If you think I've misinterpreted these rules, please let me know!) + + (C++ is stricter: a function which is inline anywhere must be inline + everywhere and must be defined identically in all the translation units + that use it.) + + Recent versions of GNU C have a -std=c99 option, but this doesn't + enable C99 inline rules yet. The manual recommends sticking to "static + inline", that being the portable subset, and promises C99 semantics in + a future release. (But it's been three years since I wrote that, and + the situation does not appear to have changed yet.) + +Strategies for using inline functions + + These rules suggest several possible models for using inline functions + in more or less portable ways. + 1. A simple portable model. Use "static inline" (either in a common + header file or just in one file). If the compiler needs to emit a + definition (e.g. to take its address, or because it doesn't want to + inline some call) then you waste a bit of space; if you take the + address of the function in two translation units then the result + won't compare equal. + For instance, in a header file: +static inline int max(int a, int b) { + return a > b ? a : b; +} + You can support legacy compilers (i.e. anything without "inline") + via -Dinline="", although this wastes space. + 2. A GNU C model. Use "extern inline" in a common header and provide a + definition in a .c file somewhere, perhaps using macros to ensure + that the same code is used in each case. For instance, in the + header file: +#ifndef INLINE +# define INLINE extern inline +#endif +INLINE int max(int a, int b) { + return a > b ? a : b; +} + + ...and in exactly one source file: +#define INLINE +#include "header.h" + Supporting legacy compilers is awkward unless you don't mind + wasting space and having multiple addresses for the same function; + you need to restrict the definitions to a in single translation + unit (with INLINE defined to the empty string) and add some + external declarations in the header file. + 3. A C99 model. Use "inline" in a common header, and provide + definitions in a .c file somewhere, via "extern" declarations. For + instance, in the header file: +inline int max(int a, int b) { + return a > b ? a : b; +} + ...and in exactly one source file: +#include "header.h" +extern int max(int a, int b); + To support legacy compilers, you have to swap the whole thing + around so that the declarations are visible in the common header + and the definitions are restricted to a single translation unit, + with inline defined away. + 4. A complicated portable mode. Use macros to choose either "extern + inline" for GNU C, "inline" for C99, or neither for a definition. + For instance, in the header: +#ifndef INLINE +# if __GNUC__ +# define INLINE extern inline +# else +# define INLINE inline +# endif +#endif +INLINE int max(int a, int b) { + return a > b ? a : b; +} + + ...and in exactly one source file: +#define INLINE +#include "header.h" + Supporting legacy compilers has the same issues as the GNU C model. + (This model won't work properly when GNU C gains C99 inline support + - instead it'll be necessary to determine which version of the + compiler is in use and whether it is a C99 mode.) + + Please report any errors. + __________________________________________________________________ + + [3]RJK | [4]Contents + +References + + 1. http://gcc.gnu.org/ + 2. http://www.iso.ch/ + 3. http://www.greenend.org.uk/rjk/ + 4. http://www.greenend.org.uk/rjk/contents.html -- cgit v1.2.3-54-g00ecf