C TYPES This assumes a rough familiarity with types. This document is not intended to be complete. The purpose is to concisely present the formal definitions of key concepts for purposes of review. The value of a variable is a location in memory. A value is considered either an address or data. A pointer variable has an address as its value. A data variable has data as its value. C constant is a value known only to the compiler, and not stored in memory at run-time. C supports only specializations of type, pointer: (* char), (* int), (* float), etc. Thus, if x is a pointer declared as (* char) or (* int), x+1 will be a pointer with an address larger than x by sizeof(char) or sizeof(int), respectively. C also supports a unique pointer, NULL. NULL is a specialization of every pointer in the lattice of types. It has the meaning "pointer to nothing". Thus, NULL+1 should never be used. Data is of type primitive or aggregate. char, int, etc. are primitive data types. * operates only on pointer variables. If * operators on a variable of type (* foo), it returns a value of type foo. & operates on any variable and returns something of type pointer. If & operates on a variable of type foo, it returns a value of type (* foo). & does not operate on constants, since it returns a pointer (an address of a location in memory). In particular, for a variable x of some pointer type, &(*x) == *(&x) == x. Aggregate data types are array, struct and union. Aggregate data types refer to data in the obvious way, when used in declarations. When an aggregate varaible is used in an expression (including arguments to functions), the aggregate is automatically coerced by the compiler into a constant pointer type, as if the aggregate variable were prefixed by &. The constant pointer points to the first byte of the storage location of the aggregate. Since a constant pointer cannot appear on the left hand side of an equation, C forbids aggregate variable names from appearing by themselves on the left hand side. When function names are used alone, without parentheses to the right, they share the above behavior of aggregate variables The operator [] operates on arrays and pointers. x[i] is equivalent to *(x+i). If x is a pointer, the reason should be clear. For an array variable, x, in the expression, *(x+i), x is coerced by the compiler into a pointer type as if prefixed by &. Hence, the same formula, *(x+i), works instead of x[i]. The operators . and -> act in the obvious way on struct or union. x->field is equivalent to (*x).field . Declarations for a global variable occur outside of any function definition. Declarations for a function appear after the function name, but before the opening "{" for the body of the function. Declarations for local variables appear immediately after a "{". The type of functions need not be declared in advance. In this case, C automatically declares the function to be of type "(int)" (i.e.: "int func()" ) immediately before its first use. Declarations in C have two purposes: to declare type information about a variable, and to allocate storage space at compile-time. All declarations specify type information. One can have multiple declarations of type (for example by including declarations of the same variable in two different ".h" files), as long as the declared types are consistent. All declarations specify type information to the compiler. Local and global declarations (not argument declarations) allocate space at compile-time. There is one exception. A global type declaration can be prefixed by the keyword, extern, in which case it does not allocate space, and is used only for its type declaration. In addition, C allows declaration of a function argument as an array with unspecified index bounds in the last component. As with all argument declarations, it is used only for type information, and not for space allocation. For example, one can declare the 1- and 2-dimensional arrays, x and y, as follows: function(x,y) int x[], y[10][]; { ... }