Chapter 5: Pointers and Arrays

5.1 Pointers and Addresses

  A typical machine has an array of consecutively numbered or addressed memory cells that may be manipulated individually or in contiguous groups. One common situation is that any byte can be a char, a pair of one-byte cells can be treated as a short integer, and four adjacent bytes form a long. A pointer is a group of cells (often two or four) that can hold an address.

  The unary operator & gives the address of an object. The & operator only applies to objects in memory: variables and array elements. It cannot be applied to expressions, constants, or register variables.

  The unary operator * is the indirection or dereferencing operator. When applied to a pointer, it accesses the object the pointer points to.

  int *ip says that the expression *ip is an int. A pointer is constrained to point to a particular kind of object: every pointer points to a specific data type. A "pointer to void" is used to hold any type of pointer but cannot be dereferenced itself. If ip points to the integer x, then *ip can occur in any context where x could.

  *ip +=1 increments what ip points to, as do ++*ip and (*ip)++. The parentheses are necessary. * and ++ have the same precedence, but associate right to left. *ip++ means fetching the object that ip ponits to, then increment ip and ip ponits to the next objcet now.

5.2 Pointers and Function Arguments

  Since C passes arguments to functions by value, there is no direct way for the called function to alter a variable in the calling function. Pointer arguments enable a function to access and change objects in the function that called it.

5.3 Pointers and Arrays

  Any operation that can be achieved by array subscripting can also be done with pointers.

  If pa points to a particular element of an array, then by definition pa+1 points to the next element, pa+i points i elements after pa, and pa-i points i elements before. Thus, if pa points to a[0] (by pa = &a[0] or pa = a), *(pa+1) refers to the contents of a[1], pa+i is the address of a[i], and *(pa+i) is the contents of a[i]. The name of an array is a synonym for the location of the initial element. a[i] can also be written as *(a+i). An array-and-index expression is equivalent to one written as a pointer and offset.

  There is one difference between an array name and a pointer that must be kept in mind. A pointer is a variable, so pa=a and pa++ are legal. But an array name is not a variable, constructions like a=pa and a++ are illegal.

  When an array name is passed to a function, what is passed is the location of the initial element. It is possible to pass part of an array to a function, by passing a pointer to the beginning of the subarray. If one is sure that the elements exist, it is also possible to index backwards in an array.

5.4 Address Arithmetic

  C is consistent and regular in its approach to address arithmetic; its integration of pointers, arrays, and address arithmetic is one of the strengths of the language.

  C guarantees that zero is never a valid address for data, so a return value of zero can be used to signal an abnormal event.

  The symbolic constant NULL is often used in place of zero, as a mnemonic to indicate more clearly that this is a special value for pointer.

  Pointer arithmetic is consistent: if we had been dealing with floats, which occupy more storage than chars, and if p were a pointer to float, p++ would advance to the next float. All the pointer manipulations automatically take into account the size of the object pointed to.

  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 of the same array, and assigning or comparing to zero (NULL). There is one exception: the address of the first element past the end of an array can be used in pointer arithmetic.

5.5 Character Pointers and Functions

  A string constant, written as "I am a string" is an array of characters. In the internal representation, the array is terminated with the null character '\0' so that programs can find the end. The length in storage is thus one more than the number of characters between the double quotes. A string constant is accessed by a pointer to its first element.

  There is an important difference between these definitions:

    char amessage[] = "now is the time";    /* an array */
    char *pmessage = "now is the time";    /* a pointer */

amessage is an array, just big enough to hold the sequence of characters and '\0' that initializes it. Individual characters within the array may be changed but amessage will always refer to the same storage. On the other hand, pmessage is a pointer, initialized to point to a string constant; the pointer may subsequently be modified to point elsewhere, but the result is undefined if you try to modify the string constants.

/* strcpy: copy t to s */
void strcpy(char *s, char *t)
{
    while (*s++ = *t++)
        ;
}
/* strcmp: return <0 if s<t, 0 if s==t, >0 if s>t */
int strcmp(char *s, char *t)
{
    for ( ; *s == *t; s++, t++)
        if (*s == '\0')
            return 0;
    return *s - *t;
}
*p++ = val;    /* push val onto stack */
val = *--p;    /* pop top of stack into val */

 5.6 Pointer Arrays; Pointers to Pointers

  Since pointers are variables themselves, they can be stored in arrays just as other variables can.

5.7 Multi-dimensional Arrays

  C provides rectangular multi-dimensional arrays, although in practice they are much less used than arrays of pointers.

  In C, a two-dimensional array is really a one-dimensional array, each of whose elements is an array.

  An array is initialized by a list of initializers in braces; each row of a two-dimensional array is initialized by a corresponding sub-list.

  If a two-dimensional array is to be passed to a function, the parameter declaration in the function must include the number of columns. More generally, only first dimension(subscript) of an array is free; all the others have to be specified.

5.8 Initialization of Pointer Arrays

5.9 Pointers vs Multi-dimensional Arrays

    int a[10][20];
    int *b[10];

  a is a true two-dimensional array: 200 int-sized locations have been set aside, and the conventional rectangular subscript calculation 20*row+col is used to find the element a[row][col]. For b, however, the definition only allocates 10 pointers and does not initialize them; initialization must be done explicitly, either statically or with code. The important advantage of the pointer array is the rows of the array may be different lengths.

5.10 Command-line Arguments

  When main is called, it is called with two arguments. The first (conventionally called argc, for argument count) is the number of command-line arguments the program was invoked with. The second (argv, for argument vertor) is a pointer to an array of character strings that contain the arguments, one per string. By convention, argv[0] is the name by which the program was invoked, so argc is at least 1. The first optional argument is argv[1] and the last is argv[argc-1]; additionally the standard requires that argv[argc] be a null pointer.

5.11 Pointers to Functions

  In C, a function itself is not a variable, but it is possible to define pointers to functions, which can be assigned, placed in arrays, passed to functions, returned by functions, and so on.

  Function name can be address of function, the & operator is not necessary.

  The generic pointer type void * is used for the pointer arguments. Any pointer can be cast to void * and back again without loss of information.

 

posted @ 2014-07-05 21:48  infraio  阅读(239)  评论(0)    收藏  举报