Explore the intimate relationship between arrays and pointers in C.
In C, arrays and pointers share a very close and fundamental relationship. This connection is key to understanding how C handles memory and array operations. The most important rule to remember is this: the name of an array, when used in an expression, decays into a pointer to its first element. For example, if you declare an array `int arr[10];`, the identifier `arr` by itself is equivalent to `&arr[0]`. It represents the memory address of the very first element of the array. Because of this, you can assign the array name directly to a pointer of the appropriate type: `int *p = arr;`. Now, the pointer `p` holds the address of the first element, `arr[0]`. This relationship is why you can use pointer arithmetic to access array elements. The expression `arr[i]` is internally treated by the compiler as `*(arr + i)`. This means 'take the starting address of the array, add an offset of `i` elements, and then dereference that new address to get the value'. This equivalence works both ways. You can use array-style square bracket notation `[]` with a pointer that points to an array. For instance, after `int *p = arr;`, `p[i]` is a valid way to access the i-th element of the array. While they can be used interchangeably in many contexts, it's important to remember a key difference: an array name is a constant pointer (you cannot change where it points), whereas a pointer variable can be reassigned to point to a different address.