Notes composed while reading C Primer Plus.
- You should use the constkeyword when you declare an
array that’s intended to be read-only.
- Arrays declared within a function and without the
statickeyword belong to the automatic storage class.
- If you partially initialize an array the remaining elements are set
to zero.
- Omitting the size from the declaration of an array allows the
compiler to determine the array size. The length can later be calculated
by dividing the size of the array in bits by the size of the first
element (i.e. sizeof days   / sizeof days[0], in whichdaysis an array).
- In the C99 standard, select elements of an array can be initialized
using designated initializers
(e.g. int arr[6] = {31,28, [3] = 31,30,31, [1] =   29};).
- Not checking array bounds allows a C program to run faster. Also,
since the value of an index may not be assigned until execution extra
code would be required to catch all index errors during runtime.
- In addition to symbolic and literal integer constants, C99 allows
the use of constant integer expressions when initializing an array.
Those expressions are used to create variable-length arrays.
- Array notation is simply a disguised use of pointers
(e.g. arr == &arr[0];, an array name is also the
address of the first element of the array).
- When adding a number to a pointer, C adds one storage unit, which
for arrays means adding one element of the specified type
(e.g. arr + 2 == &arr[2]). This is one reason why you
have to declare the type of object to which the pointer points. Applying
the*operator to a pointer yields the value stored in the
pointed-to object (e.g.*(arr + 2) == arr[2]). Applying theloperator increases its value by the size of the
pointed-to type. There is no significant technical advantage to pointer
notation over array notation.
- Rather than passing a pointer to an array and a integer parameter to
indicate the number of elements, one can also pass two pointers, which
indicate where the array begins and ends.
- C guarantees that when it allocates space for an array, a pointer to
the first location after the end of the array is a valid pointer.
- The increment operator only works with pointer notation. Also, it is
closer to machine language and will lead to more efficient code with
some compilers. However, many programmers believe that the programmer’s
main concerns should be correctness and clarity, while code optimization
should be left to the compiler.
- When subtracting an integer from a pointer, the pointer has to be
the first operand or a pointer to an integer.
- You can find how far apart two pointers are, which point to the same
array, by subtracting one from the other.
- Do not dereference an uninitialized pointer by storing a value in
the location to which it points. Creating a pointer only allocates
memory to store that pointer itself. Therefore, there is no knowing
where the assigned value will go. The function should be passed
arguments by value unless the program needs to alter the value. This
preserves the integrity of the data.
- If an array is passed as an argument then it must be passed as a
pointer in order to preserve efficiency. This increases the chance of a
programming error corrupting the original data. This is solved in ANSI C
by using the constkeyword when declaring the formal
parameter in the prototype and the function definition.
- The constkeyword can be used to create symbolic
constants, which can be done with the#definedirective
too, butconstcan additionally create constants arrays,
constant pointers and pointers to constants.
- Declaring a pointer with the constkeyword
(i.e.const double *ptr) means that the value cannot
change, but where it points can be change. Conversely, declaring a
pointer likedouble * const ptr, allows the value to
change, but not the address.
- It is not possible to assign the address of constant data to a non
constant pointer, and similarly use a constant variable as an argument
in a function, whose parameter was not declared to be constant.
- With a multidimensional array (e.g. int arr[4][2]) the
values ofarrandarr[0]are the same, but the
value ofarr[0]++doesn’t equalarr++, because
they are being incremented by objects of different sizes. Also, note
thatarris the address of an address and must be
dereferenced twice to get an ordinary value, which is an example of
double indirection.
- To point to a multidimensional array
(e.g. int arr[4][2];) one needs to point to an array of the
correct size and type (i.e.int (*ptr)[2];). While,int *ptr[2];would create an array with two pointers toints.
- The rules for assigning one pointer to another are tighter than the
rules for numeric types. For example, you can assign an intvalue to adoublevariable without using type conversion,
but you can’t do the same for pointers of those two types.
- Given the declaration int arr[3][2];, thenarris a pointer-to-array-of-two-ints or pointer-to-int[2].
That is the type associated with the individual pointer, even though the
address it points to is the first element of an array containing three
pointers. So whenarris incremented, it increases by the
type associated with it.
- Function declarations including a multidimensional array as a
parameter only require the type of the pointer to be specified in either
notation (i.e. int   sum(int arr[][4], int rows);orint sum(int (*arr)[4], int rows);). The declarationint sum(int arr[][], int rows);is invalid because the type
is not correctly specified. Conversely the3inint sum(int arr[3][4], int   rows);will be ignored.
- Before the introduction of C99 it was cumbersome to write a function
to process a two dimensional array because constants were required for
the dimensions in an array declaration. Variable-length arrays allow the
use of variables when dimensioning an array. For example,
int arr[x][y];is a valid statement ifxandywere previously defined.
- Variable-length arrays require the automatic storage class (see
above). The word “variable” in VLA refers to the use of a variable when
specifying the array dimensions, not that the length of the array can be
modified.
- C99 introduced compound literals that represent arrays and
structures, just as there had been for int,double,charand strings. An example of using
a array compound literal is to pass it as an actual argument to a
function. For example,total = sum ((int []){1,2,3,3,0}, 5);.