| 14.12 goto can only jump to a label inside the same function. | |
| 14.13 goto should not jump over variable initializations. | |
| D Premature optimization is the root of all evil. | |
| 15.1 Do not trade off safety for performance. | |
| 15.2 Optimizers are clever enough to eliminate unused initializations. | |
| 15.3 The different notations of pointer arguments to functions result in the same binary code. | |
| 15.4 Not taking addresses of local variables helps the optimizer because it inhibits aliasing. | |
| 15.5 Inlining can open up a lot of optimization opportunities. | |
| 15.6 Adding a compatible declaration without the inline keyword ensures the emission of the function symbol in the current TU. | |
| 15.7 An inline function definition is visible in all TUs. | |
| 15.8 An inline definition goes in a header file. | |
| 15.9 An additional declaration without inline goes in exactly one TU. | |
| 15.10 Only expose functions as inline if you consider them to be stable. | |
| 15.11 All identifiers that are local to an inline function should be protected by a convenient naming convention. | |
| 15.12 inline functions can’t access identifiers of static functions. | |
| 15.13 inline functions can’t define or access identifiers of modifiable static objects. | |
| 15.14 A restrict-qualified pointer has to provide exclusive access. | |
| 15.15 A restrict-qualification constrains the caller of a function. | |
| E Don’t speculate about the performance of code; verify it rigorously. | |
| 15.16 Complexity assessment of algorithms requires proofs. | |
| 15.17 Performance assessment of code requires measurement. | |
| 15.18 All measurements introduce bias. | |
| 15.19 Instrumentation changes compile-time and runtime properties. | |
| 15.20 The relative standard deviation of run times must be in a low percentage range. | |
| 15.21 Collecting higher-order moments of measurements to compute variance and skew is simple and cheap. | |
| 15.22 Runtime measurements must be hardened with statistics. | |
| 16.1 Whenever possible, prefer an inline function to a functional macro. | |
| 16.2 A functional macro shall provide a simple interface to a complex task. | |
| 16.3 Macro replacement is done in an early translation phase, before any other interpretation is given to the tokens that compose the program. | |
| 16.4 (macro retention) If a functional macro is not followed by (), it is not expanded. | |
| 16.5 The line number in __LINE__ may not fit into an int. | |
| 16.6 Using __LINE__ is inherently dangerous. | |
| 16.7 Stringification with the operator # does not expand macros in its argument. | |
| 16.8 When passed to a variadic parameter, all arithmetic types are converted as for arithmetic operations, with the exception of float arguments, which are converted to double. | |
| 16.9 A variadic function has to receive valid information about the type of each argument in the variadic list. | |
| 16.10 Using variadic functions is not portable unless each argument is forced to a specific type. | |
| 16.11 Avoid variadic functions for new interfaces. | |
| 16.12 The va_arg mechanism doesn’t give access to the length of the va_list. | |
| 16.13 A variadic function needs a specific convention for the length of the list. | |
| 16.14 The result type of a _Generic expression is the type of the chosen expression. | |
| 16.15 Using _Generic with inline functions adds optimization opportunities. | |
| 16.16 The type expressions in a _Generic expression should only be unqualified types: no array types, and no function types. | |
| 16.17 The type expressions in a _Generic expression must refer to mutually incompatible types. | |
| 16.18 The type expressions in a _Generic expression cannot be a pointer to a VLA. | |
| 16.19 All choices expression1 ... expressionN in a _Generic must be valid. | |
| 17.1 Side effects in functions can lead to indeterminate results. | |
| 17.2 The specific operation of any operator is sequenced after the evaluation of all its operands. | |
| 17.3 The effect of updating an object with any of the assignment, increment, or decrement operators is sequenced after the evaluation of its operands. | |
| 17.4 A function call is sequenced with respect to all evaluations of the caller. | |
| 17.5 Initialization-list expressions for array or structure types are indeterminately sequenced. | |
| 17.6 Each iteration defines a new instance of a local object. | |
| 17.7 goto should only be used for exceptional changes in control flow. | |
| 17.8 Each function call defines a new instance of a local object. | |
| 17.9 longjmp never returns to the caller. | |
| 17.10 When reached through normal control flow, a call to setjmp marks the call location as a jump target and returns 0. | |
| 17.11 Leaving the scope of a call to setjmp invalidates the jump target. | |
| 17.12 A call to longjmp transfers control directly to the position that was set by setjmp as if that had returned the condition argument. | |
| 17.13 A 0 as a condition parameter to longjmp is replaced by 1. | |
| 17.14 setjmp may be used only in simple comparisons inside controlling expression of conditionals. | |
| 17.15 Optimization interacts badly with calls to setjmp. | |
| 17.16 Objects that are modified across longjmp must be volatile. | |
| 17.17 volatile objects are reloaded from memory each time they are accessed. | |
| 17.18 volatile objects are stored to memory each time they are modified. | |
| 17.19 The typedef for jmp_buf hides an array type. | |
| 17.20 C’s signal-handling interface is minimal and should only be used for elementary situations. | |
| 17.21 Signal handlers can kick in at any point of execution. | |
| 17.22 After return from a signal handler, execution resumes exactly where it was interrupted. | |
| 17.23 A C statement may correspond to several processor instructions. | |
| 17.24 Signal handlers need types with uninterruptible operations. | |
| 17.25 Objects of type sig_atomic_t should not be used as counters. | |
| 17.26 Unless specified otherwise, C library functions are not asynchronous signal safe. | |
| 18.1 If a thread T0 writes a non-atomic object that is simultaneously read or written by another thread T1, the behavior of the execution becomes undefined. | |
| 18.2 In view of execution in different threads, standard operations on atomic objects are indivisible and linearizable. | |
| 18.3 Use the specifier syntax _Atomic(T) for atomic declarations. | |
| 18.4 There are no atomic array types. | |
| 18.5 Atomic objects are the privileged tool to force the absence of race conditions. | |
| 18.6 A properly initialized FILE* can be used race-free by several threads. | |
| 18.7 Concurrent write operations should print entire lines at once. | |
| 18.8 Destruction and deallocation of shared dynamic objects needs a lot of care. | |
| 18.9 Pass thread-specific data through function arguments. | |
| 18.10 Keep thread-specific state in local variables. | |
| 18.11 A thread_local variable has one separate instance for each thread. | |
| 18.12 Use thread_local if initialization can be determined at compile time. | |
| 18.13 Mutex operations provide linearizability. | |
| 18.14 Every mutex must be initialized with mtx_init. | |
| 18.15 A thread that holds a nonrecursive mutex must not call any of the mutex lock functions for it. | |
| 18.16 A recursive mutex is only released after the holding thread issues as many calls to mtx_unlock as it has acquired locks. | |
| 18.17 A locked mutex must be released before the termination of the thread. | |
| 18.18 A thread must only call mtx_unlock on a mutex that it holds. | |
| 18.19 Each successful mutex lock corresponds to exactly one call to mtx_unlock. | |
| 18.20 A mutex must be destroyed at the end of its lifetime. | |
| 18.21 On return from a cnd_t wait, the expression must be checked again. | |
| 18.22 A condition variable can only be used simultaneously with one mutex. | |
| 18.23 A cnd_t must be initialized dynamically. | |
| 18.24 A cnd_t must be destroyed at the end of its lifetime. | |
| 18.25 Returning from main or calling exit terminates all threads. | |
| 18.26 While blocking on mtx_t or cnd_t, a thread frees processing resources. | |
| 19.1 Every evaluation has an effect. | |
| 19.2 If F is sequenced before E, then F → E. | |
| 19.3 The set of modifications of an atomic object X are performed in an order that is consistent with the sequenced-before relation of any thread that deals with X. |