summaryrefslogtreecommitdiff
path: root/docs
diff options
context:
space:
mode:
authorAndreas Baumann <abaumann@yahoo.com>2009-03-30 21:15:37 +0200
committerAndreas Baumann <abaumann@yahoo.com>2009-03-30 21:15:37 +0200
commitab86dda9cc66a946d257ecb96cbf8a17662af045 (patch)
tree18ba2cd155f16298f78e1e06987afdec5725d1d7 /docs
parent9010a500e7b1c8e7f16b0093b7cf456e07dd7d85 (diff)
downloadwolfbones-ab86dda9cc66a946d257ecb96cbf8a17662af045.tar.gz
wolfbones-ab86dda9cc66a946d257ecb96cbf8a17662af045.tar.bz2
added C inline docu
Diffstat (limited to 'docs')
-rw-r--r--docs/port/inline.txt206
1 files changed, 206 insertions, 0 deletions
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