(char *)0 as a NULL pointer
When function prototype is in scope, argument passing becomes "assignment context" and most casts can be safely omitted since the prototype tells the compiler that a pointer type is required and of which type.
Function prototypes cannot provide the types for variable arguments in a variable length argument list and explicit casts are still required.
Macro NULL;
ANSI C Rationale - http://www.lysator.liu.se/c/rat/title.html
-- from http://www.lysator.liu.se/c/c-faq/c-2.html"Equivalence" refers to the following key definition:
(The exceptions are when the array is the operand of asizeofor&operator, or is a literal string initializer for a character array.)An lvalue [see question 2.5] of type array-of-T which appears in an expression decays (with three exceptions) into a pointer to its first element; the type of the resultant pointer is pointer-to-T.
Arrays and pointers
int array[NROWS][NCOLUMNS]; f(array);the function's declaration should match:
f(int a[][NCOLUMNS]) {...}
or f(int (*ap)[NCOLUMNS]) {...} /* ap is a pointer to an array */
Dynamic Multidimensional array
It is usually best to allocate an array of pointers, and then initialize each pointer to a dynamically-allocated "row." Here is a two-dimensional example:
int **array1 = (int **)malloc(nrows * sizeof(int *));
for(i = 0; i < nrows; i++)
array1[i] = (int *)malloc(ncolumns * sizeof(int));
(In "real" code, of course, malloc would be declared correctly, and each return value checked.)
You can keep the array's contents contiguous, while making later reallocation of individual rows difficult, with a bit of explicit pointer arithmetic:
int **array2 = (int **)malloc(nrows * sizeof(int *));
array2[0] = (int *)malloc(nrows * ncolumns * sizeof(int));
for(i = 1; i < nrows; i++)
array2[i] = array2[0] + i * ncolumns;