C CLP cheat sheet
C CLP · Keep the key ideas within reach.
Program Structure, Compilation, and Preprocessing
Translation phases run in order: trigraph replacement, line splicing (backslash-newline), tokenization, preprocessing directives, escape conversion, string concatenation, then compilation proper.
The preprocessor operates on preprocessing tokens before any type information exists; macros are pure token substitution and have no scope or type checking.
Object-like macro
#define N 10substitutes tokens; function-like macro#define SQ(x) ((x)*(x))requires parentheses around parameters and the whole body to avoid precedence bugs.#stringizes a macro parameter and##pastes tokens; both are only valid inside function-like macro replacement lists.#include "file"searches implementation-defined locations (typically the current directory first);#include <file>searches system include paths.Include guards (
#ifndef H/#define H/#endif) or#pragma onceprevent multiple inclusion within one translation unit.Conditional compilation uses
#if,#ifdef,#ifndef,#elif,#else,#endif;defined(X)is only meaningful inside#if/#elifexpressions.The predefined macros
__FILE__,__LINE__,__DATE__,__TIME__,__STDC__expand at preprocessing time;__func__is a function-scope identifier, not a macro.Separate compilation: each .c file plus included headers forms a translation unit; the linker resolves external symbols across object files, so a function declared but never defined yields a link error, not a compile error.
Data Types, Declarations, and Type Conversions
Core types:
char,short,int,long,long long(signed/unsigned),float,double,long double, plus_Bool; sizes are implementation-defined except minimum ranges guaranteed by the standard.Integer conversion rank orders
char<short<int<long<long long; usual arithmetic conversions promote operands to a common type based on rank and signedness.Integer promotions convert any type of rank below
inttoint(orunsigned intifintcannot represent all values).Assigning a signed negative value to an unsigned type is defined: it wraps modulo 2^N; signed overflow is undefined behavior.
constmakes an object read-only after initialization;volatileforces every access to actually occur and forbids caching in registers.typedefcreates a type alias, not a new type; it does not introduce a tag namespace entry.Declarations vs definitions: a declaration introduces a name; a definition allocates storage or supplies a function body.
extern int x;declares;int x;at file scope is a tentative definition.sizeofyieldssize_t(an unsigned type) and does not evaluate its operand when the type is not a variable-length array.
Operators, Expressions, and Evaluation Order
Precedence (high to low): postfix
() [] . ->; unary! ~ + - * & ++ -- sizeof; cast; multiplicative; additive; shift; relational; equality; bitwise AND, XOR, OR; logical AND, OR; conditional?:; assignment; comma.&&and||short-circuit and introduce sequence points; the right operand is not evaluated when the result is already determined.The
,operator evaluates left then right and yields the right value; it is a sequence point. It is distinct from the comma separating function arguments.Unsequenced modification of the same scalar between sequence points (e.g.
i = i++) is undefined behavior.&,|,^do not short-circuit and require integer operands;~is bitwise complement,!is logical negation.Shift counts negative or >= the operand width are undefined; right shift of a negative signed value is implementation-defined.
The conditional operator
a ? b : cevaluates only one of b or c; usual arithmetic conversions apply to b and c.Assignment operators are right-associative;
a = b = cassigns c to b then b to a.
Control Flow and Statements
if/elsebindselseto the nearest unmatchedif; braces are needed to control grouping.switchrequires an integer expression;caselabels must be integer constant expressions, anddefaultappears at most once.switchfalls through unless abreakorreturnis reached;breakexits the switch, not an enclosing loop.for (init; cond; step): init runs once, cond is checked before each iteration, step runs after each body execution;continuejumps to the step expression.whileanddo ... whilediffer:doexecutes the body at least once and its condition is tested after the body.breakexits the innermost loop or switch;continueskips to the next iteration of the innermost loop.gotojumps to a label within the same function; it cannot cross function boundaries and cannot jump into a variable-length array's scope.A null statement is just
;; an empty body afterwhile(...);is a common logic error.
Functions, Scope, Storage Duration, and Linkage
Functions are pass-by-value in C; to modify a caller's object, pass a pointer and dereference inside the function.
Default argument promotions apply to arguments of prototypes with
...(variadic) or to functions declared without a prototype:floatpromotes todouble, small integers promote toint.staticat file scope gives internal linkage;staticat block scope gives static storage duration with no linkage.externdeclares a name with external linkage; a definition withoutexternat file scope has external linkage by default.Block scope begins at declaration and ends at the closing brace; file scope extends to end of translation unit; function prototype scope covers only the parameter list.
Storage durations: automatic (block variables), static (file-scope and
staticlocals), thread (_Thread_local), allocated (frommalloc).registeris a hint only; taking the address of aregisterobject is a constraint violation.A function with no parameters should be declared
f(void);f()means unspecified parameters in older-style declarations.
Pointers and Arrays
An array name in an expression (except as operand of
sizeof,&, or a string literal initializer) decays to a pointer to its first element.Pointer arithmetic is scaled by the pointed-to type:
p + 1advancessizeof(*p)bytes; only pointers into the same array (or one past the end) may be subtracted.a[i]is defined as*(a + i);i[a]is therefore equivalent.&ayields a pointer to the whole array with typeT (*)[N];adecays toT *.A pointer to
voidconverts to and from any object pointer type without a cast; function pointers are not convertible tovoid *in strictly conforming code.NULLis a null pointer constant; dereferencing it is undefined behavior. Compare pointers with==/!=rather than relational operators except within an array.Multidimensional arrays are arrays of arrays;
int a[3][4]passes asint (*)[4], notint **.Pointer to function:
int (*fp)(int); calling through a null or dangling function pointer is undefined behavior.
Strings and Character Handling
A C string is a
chararray terminated by a null character'\0'; the terminator is not counted bystrlenbut must fit in the buffer.strlenreturnssize_tand scans until the terminator; it does not include'\0'in the count.strcpy/strcatdo not bounds-check;strncpymay leave no terminator and pads with zeros;snprintfalways terminates if size > 0.strcmpreturns negative, zero, or positive for lexicographic comparison of unsigned char values;strncmplimits the comparison length.<ctype.h>functions (isdigit,isalpha,toupper, etc.) require an argument representable asunsigned charorEOF; passing a negativecharis undefined behavior.String literals are arrays of
charwith static storage duration; modifying a literal (via a non-const pointer) is undefined behavior.Adjacent string literals are concatenated during translation phase 6, before compilation.
memcpycopies non-overlapping regions;memmovehandles overlapping regions; both takesize_tbyte counts and do not stop at'\0'.
Dynamic Memory Management
malloc(size)returns uninitialized storage orNULL;calloc(n, size)zero-initializes and may overflow-check;reallocmay move the block and frees the old pointer on success.free(NULL)is a no-op; freeing a pointer not returned by an allocation function, or freeing twice, is undefined behavior.After
free(p),pis indeterminate (dangling); settingp = NULLafter freeing prevents accidental reuse.realloc(p, 0)is implementation-defined: it may freepand returnNULL, or return a unique pointer.mallocreturns memory suitably aligned for any object type; casting its return value is unnecessary in C and can hide a missing prototype error.Allocated storage has no declared type until written; effective type rules govern reads of the stored bytes.
Every successful allocation must be matched by exactly one
free; leak detection requires tracking ownership across functions.allocais non-standard and frees on function return; standard C offers onlymallocfamily andaligned_allocfor aligned storage.
Structures, Unions, Enumerations, and Bit-fields
Struct members are laid out in declaration order with possible padding;
sizeof(struct)may exceed the sum of member sizes.offsetof(type, member)from<stddef.h>gives the byte offset of a member.A struct may be assigned, passed, and returned by value; it may not be compared with
==.A pointer to a struct and a pointer to its first member have the same address; a cast between them is guaranteed to work.
Unions overlay members in shared storage; reading a member other than the last written is implementation-defined (type punning via union is common but not strictly portable).
Enumeration constants have type
intand are integer constant expressions; the underlying type of the enum itself is implementation-defined.Bit-fields are declared as
type name : width; width must not exceed the bit width of the type, and taking the address of a bit-field is not allowed.Bit-field layout, ordering, and padding are implementation-defined; use masks and shifts for portable bit manipulation.
Standard Library Usage and File I/O
FILE *streams are opened withfopen(path, mode)where mode includes"r","w","a","r+","w+","a+", optionally withb; check forNULLon failure.fcloseflushes buffered output and releases the stream; failing to close can lose buffered data.fgetc/fputchandle single characters;fgetsreads at most n-1 characters plus a terminator;fread/fwritetransfer fixed-size records.fseek(stream, offset, whence)withSEEK_SET,SEEK_CUR,SEEK_END;ftellreturns the current position aslong.feofonly reports end-of-file after a read attempt has failed; it is not a predictive test.printfformat specifiers:%d,%u,%ld,%zuforsize_t,%f,%e,%g,%c,%s,%p,%%; mismatched types are undefined behavior.scanfreturns the number of items successfully assigned;%sreads a whitespace-delimited token and does not bounds-check without a width, e.g.%9s.<stdlib.h>providesatoi,strtol(with end pointer and base),qsort(comparator returns negative/zero/positive), andbsearch;exitflushes and closes all streams,_Exitdoes not.