Summary of C
Types
- statically-typed
- The type of every expression (except those involving VLAs) is known at compile-time
Arithemetic types
1==sizeof(char) <= sizeof(short) <= sizeof(int) <= sizeof(long) <= sizeof(long long)
sizeof(signed T)==sizeof(unsigned T)
for every \(T \in\{\)char, short, int, long, long long
}- short and int are at least 16 bits. long is at least 32 bits. long long is at least 64 bits.
- Range of signed types: \(\left[-2^{N-1}, 2^{N-1}-1\right]\). Range of unsigned types: \(\left[0,2^N-1\right]\)
- Whether char is signed or not is implementation-defined.
- Signed integer overflow is undefined behavior.
- Unsigned arithmetic never overflows: It is performed modulo \(2^N\), where \(N\) is the number of bits of that type.
Pointer types
PointeeType *
- For
T!=U
,T *
andU *
are different types. - The value of a pointer of type
T *
is the address of an object of typeT
. - Null pointer: The pointer holding the null pointer value, which is a special value indicating that the pointer is "pointing nowhere".
- A null pointer can be obtained from
NULL
.
- A null pointer can be obtained from
&var
returns the address of var. The return type is pointer to the type of var .- Only when a pointer is actually pointing to an object is it dereferenceable.
*ptr
, whereptr
is not dereferenceable, is undefined behavior.
Array types
ElemType [N]
- Different Types
N
should be compile-time constant. Otherwise it is a VLA.- Valid index range: \([0, N)\). Subscript out of range is undefined behavior.
- Decay:
a
->&a[0]
,T[N]
->T *
Pointer to array: T (*)[N]
. Array of pointers: T *[N]
.
struct
A special data type consisting of a sequence of members.
- The type name is
struct StructName
. sizeof (struct X)
\(\geqslant \sum_{\text {member } \in X}\)sizeof (member)
Variables
- Declare:
Type varName
- Array:
ElemType varName[N]
- Pointer to Array:
T (*varName)[N]
- Array:
- Initialize:
= initializer
- Brace-enclosed list initializer for arrays and
struct
s:= { ... }
- Designators for arrays:
= {[3] = 5, [7] = 4}
- Designators for
struct
s:= {.mem1 = x, .mem2 = y}
.
- Designators for arrays:
- Brace-enclosed list initializer for arrays and
Initialization
Variable declared without explicit initializer
- For global or local
static
variables, they are empty-initialized:0
for integer types,+0.0
for floating-point types,- null pointer value for pointer types.
- For local non-
static
variables, they are uninitialized, holding indeterminate values
These rules apply recursively to the elements of arrays and the members of struct
s.
Any use of the value of an uninitialized variable is undefined behavior
Scopes and name lookup
Expressions
- Operator precedence, associativity, and evaluation order of operands
- The only four operators whose operands have deterministic evaluation order:
&&
and||
: short-circuit evaluation?:
,
(not in a function call or in an initializer list)
- If the evaluation order of
A
andB
is unspecified, and if- both
A
andB
contain a write to an object, or - one of them contains a write to an object, and the other one contains a read to that object
- both
- then the behavior is undefined.
Arithmetic operators
+, -, *, /, %
- Division: Truncated ->
0
(a / b) * b + (a % b) == a
- For
+
,-
,*
and/
, the operands undergo a series of type conversions to a common type.
- Division: Truncated ->
- Bitwise
~, &, |, ^, <<, >>
- Compound
a op= b <=> a = a op b
- In/Decrease
- Be careful with signed overflows
Pointer arithmetic
- Pointer arithmetic: Plus(Increase), Minus(Decrease)
- Pointer arithmetic uses the units of the pointed-to type.
p + i == (char *)p + i * sizeof(*p)