K&R C
- Book PDF
Chapter 2 - Types, Operators, and Expressions
Right shifting an unsigned quantity always fits the vacated bits with zero. Right shifting a signed quantity will fill with bit signs (‘arithmetic shift’) on some machines and with 0-bits (‘logical shift’) on others.
The unary operator ~ yields the one’s complement of an integer; that is, it converts each 1-bit into a 0-bit and vice versa. For example
x = x & ~077
sets the last six bits of x to zero. Note that x & ~077 is independent of word length, and is thus preferable to, for example, x & 0177700, which assumes that x is a 16-bit quantity. The portable form involves no extra cost, since ~077 is a constant expression that can be evaluated at compile time.
Chapter 5 - Pointers & Arrays
-
a ‘pointer to void’ is used to hold any type of pointer but cannot be dereferenced itself
-
C functions are pass-by-value, so some classes of functions are impossible to express without pointers
- Are structs recursively pass-by-value as well, regardless of size?
-
It is possible to pass part of an array to a function, by passing a pointer to the beginning of the subarray. For example, if $a$ is an array:
f(&a[2])
and
f(a+2)
both pass to the function $f$ the address of the subarray that starts at
a[2]
. Within $f$, the parameter declaration can read:f(int arr[]) { ... }
or
f(int *arr) { ... }
So as far as $f$ is concerned, the fact that the parameter refers to part of a larger array is of no consequence.
-
The valid pointer operations are assignment of pointers of the same type, adding or subtracting a pointer and an integer, subtracting or comparing two pointers to members of the same array, and assigning or comparing to zero. All other pointer arithmetic is illegal. It is not legal to add two pointers, or to multiply or divide or shift or mask them, or to add float or double to them, or even, except for void *, to assign a pointer of one type to a pointer of another type without a cast.