5.2. Header Files
You may, from time to time, find yourself browsing the Linux header files. You are likely to find some constructs there that go beyond ANSI/ISO-compliant C code. A few, at least, are worth understanding. All of the constructs documented here are more fully documented in the gcc info documentation.
5.2.1. long long
The long long type denotes a storage unit at least as large as a long. On Intel i86 and other 32-bit platforms, long is 32 bits wide, and long long is 64 bits wide. On 64-bit platforms, pointers and long long are 64 bits wide, and long may be 32 or 64 bits wide depending on the platform. The long long type is supported in the "C99" dialect of C (ISO/IEC 9899:1999), and has been a long-standing extension to C provided by gcc.
5.2.2. Inline Functions
In certain parts of the Linux header files (system-specific ones, in particular), inline functions are used pervasively. They are as fast as macros (no function call overhead is incurred) but provide all the type checking available with a normal function call. Code that calls inline functions must be compiled with at least minimal optimization on (-O).
5.2.3. Alternative Extended Keywords
In gcc, every extended keyword (keywords not covered by the ANSI/ISO standards) has two versions: the keyword itself and the keyword surrounded by two underscore characters on each side. When the compiler is used in standard-compliant mode (usually, because the -ansi argument was used), the normal extended keywords are not recognized. So, for example, the attribute keyword is written as _ _attribute_ _ in the header files.
The attribute extended keyword is used to tell gcc more about a function, variable, or declared type than is possible in ANSI/ISO-compliant C code. For example, the aligned attribute tells gcc exactly how to align a variable or type; the packed attribute specifies that padding not be used; and noreturn specifies that a function never returns, which allows gcc to optimize better and avoid spurious warnings.
Function attributes are declared by adding them to the function declaration, like this:
void die_ die_die(int, char *) _ _attribute_ _ ((_ _noreturn_ _));
The attribute declaration is placed between the closing parenthesis and the semicolon of the declaration and consists of the attribute keyword followed by the attributes in double parentheses. If there are multiple attributes, use a comma-separated list.
int printm(char *, ...) __attribute__((const, format (printf, 1, 2))) ;
This says that printm does not examine any values other than its arguments and has no side effects related to code generation (const), that gcc should check the arguments given to it as it checks the arguments to printf(), and that the first argument is the format string and the second argument is the first substituted parameter (format).
We cover some attributes in context (for instance, building shared libraries in Chapter 8), and you can find all the documentation on attributes in the gcc Texinfo documentation.