# Arrays, String Constants and Pointers

## Arrays

• An array is declared as datatype name[constant-size] and groups one or more instances of a datatype into one addressable place
• constant-size may be an expression, but the expression must evaluate to a constant, like:
```	#define MAX_SIZE	16
...
int list[MAX_SIZE + 1];
```
• C arrays begin at element 0, so an array definition like `int a[3];` would create three `int` elements, addressable as `a[0]`, `a[1]`, and `a[2]`
• Note that even tough the definition says `a[3]`, there is no element named `a[3]`
• As with other variables, global and static array elements are initialized to 0 by default, and automatic array elements are filled with garbage values
• Arrays can be initialized using one or more values in braces,
like `int a[3] = {5, -2, 17};`
• Pre-ANSI C compilers may not allow initializers on automatic arrays
• If a list of initialization values is present but no constant-size is specified, the size of the array is the same as the number of initialization values
• `int q[] = {1, 2, 3};` is the same as
`int q[3] = {1, 2, 3};`
• To declare an external reference to an array defined in another file,
use `extern int a[];`

## String Constants

• In C, an array of type `char` is used to represent a character string, the end of which is marked by a byte set to 0 (also known as a NUL character)
• The following definitions both set their arrays to the same values:
```	int str1[] = {'a', 'b', 'c', '\0'};
int str2[] = "abc";
```
• ANSI C also allows a definition like `int str[3] = "abc";` which is the same as `int str[3] = {'a', 'b', 'c'};` (omitting the final NUL character)

## Multidimensional Arrays

• Multidimensional arrays are simply arrays of arrays (of arrays of arrays...)
• A multidimensional array like `m[3][2]` is stored in consecutive memory locations as m[0][0], m[0][1], m[1][0], m[1][1], m[2][0], m[2][1]

## Pointers

• A pointer is a variable that contains the address of a variable
• There are two operators associated with pointers:
• The `&` operator returns the address of its argument
• The `*` operator dereferences its argument to access the object pointer to by the pointer
• One simple example of a pointer is:
```	int i, j;
int *p;	/* pointer to `int' */

i = 6;
p = &i;	/* set `p' to address of `i' */
j = *p;	/* set `j' to 6 (value of `i') */
*p = 5;	/* set `i' to 5 */
```
• Pointers can either contain an address or a special value called a null pointer which is different from all valid pointers
• A 0 in a pointer context will be converted to a null pointer at compile time
• There is also a preprocessor macro NULL (defined in either `<stdio.h>` or `<stdlib.h>`)
• An expression like `if (!ptr) statement` will cause statement to be evaluated if `ptr` is a null pointer since `if (ptr)` is the same as `if (ptr == 0)` and since the `0` is converted to a null pointer in a pointer context, the code is implicitly comparing `ptr` against a null pointer
• Similarly, `if (ptr) statement` will evaluate statement if `ptr` is not a null pointer
• Pointers cannot point at:
• constants (like 3, not `const`s like `const int a;`) since the value 3 doesn't have a permanent memory address
• `register` variables since registers are not in memory and thus do not have a memory address
• expressions like `(8 * k)`, which are roughly the same as constants in that they don't have a permanent memory address

## Pointers and Arrays

• Pointers can be treated as arrays
• This code:
```int
identical(void)
{
int a[3] = {6, 3, 7};
int *p = &a[0];	/* point `p' at the first element of `a' */

if (a[0] == p[0] && a[1] == p[1] && a[2] == p[2])
return 1;
else
return 0;
}
```
would return 1, since `p[n]` points to `a[n]` for all valid values of n
• Pointers are not, however, the same as arrays
• This is one of the most confusing parts of C, so here are three different ways of stating the difference between an array `a` and a pointer `p` which points to the first element of ```a ```:
• The technical explanation: arrays are accessed using direct addressing, pointers are accessed using indirect addressing
• The less technical explanation: `a` is an address, `p` is an address which holds the address of `a`
• The extremely wordy explanation: to retrieve value from `a[n]`, the computer starts at address `a`, moves n past it and fetches value from there; to retrieve value from `p[n]`, the computer starts at address `p`, fetches the address stored there and adds n to it, then fetches value from the resulting address
• Most of the time, however, pointer and array accesses can be treated as acting the same, the major exceptions being:
• the `sizeof` operator
• `sizeof(array)` returns the amount of memory used by all elements in `array`
• `sizeof(pointer)` only returns the amount of memory used by the `pointer` variable itself
• the `&` operator
• `&array` is an alias for `&array[0]` and returns the address of the first element in `array`
• `&pointer` returns the address of `pointer`
• a string literal initialization of a character array
• `char array[] = "abc"` sets the first four elements in `array` to 'a', 'b', 'c', and '\0'
• `char *pointer = "abc"` sets `pointer` to the address of the "abc" string (which may be stored in read-only memory and thus unchangeable)
• Additionally, an array cannot be resized or reassigned

## Pointer Arithmetic

• `ptr++` increments `ptr` by the appropriate amount to reach the next entry of `ptr`'s datatype
• If, for example, `ptr` points to address 0xff00:
• if `ptr` is a `char`, `ptr++` will set `ptr` to 0xff01
• if `ptr` is an `int` (and an `int` is 4 bytes long), `ptr++` will set `ptr` to 0xff04
• If `ptr1` is pointing at `a[0]` and `ptr2` is pointing at `a[3]`, then `ptr2 - ptr1` returns the integer value 3, no matter what the datatype of `a` is
• Similarly, equality, inequality and other arithmetic relations all work appropriately, as long as the pointers being compared both point to the same group of elements
• That is, if `a` and `b` are different arrays, then given `ptr1 = &a[0]` and `ptr2 = &b[0]`, it is impossible to predict whether `ptr1 < ptr2` or `ptr1 > ptr2` (though `ptr1 != ptr2` will always be true)
Previous, Next, Index