Understanding Pointers, Arrays, and References
In a declaration, [ ] means array of and * means pointer to.
Two Lines That Look Alike
A declaration is a short line of code that tells the language what a name refers to and what kind of data it holds. Two of the most common declarations in C look almost identical on the page, yet they do very different jobs. One creates a collection of values. The other creates a variable that refers to a single object somewhere else. This article teaches you to read both, so that you can tell them apart before you see any further code.
What do you think happens?
Before reading on, predict what the declaration char v[6]; creates.
Reveal answer
Six char elements, indexed from v[0] to v[5]
The brackets in char v[6]; mean array of, so the name v refers to an array of six char elements. The source states that this declaration creates an array of six char elements, indexed from v[0] to v[5].
Tracing the Array Declaration
Take the declaration char v[6]; and follow what it sets up. The name is v. The type char says what each element holds. The number inside the brackets, 6, says how many elements the array contains. In the declaration, the brackets mean array of, so the whole statement can be read as v is an array of six char. The source also says that the size given in an array declaration must be a constant expression.
- char: the type of each element
- v: the name of the whole collection
- [6]: the array holds six elements
The diagram lists every valid index for v. Read it from left to right: six slots exist, labeled v[0] through v[5]. The label v[6] belongs to no slot in v at all. Writing to or reading from v[6] would fall outside the array.
Why Counting Starts at Zero
Every array in this description starts at index 0, which is its lower bound. The lower bound is the first valid index, and it is not 1. Because of this, the valid indices for an array of size $n$ run from $0$ to $n-1$. The last valid index is always one less than the number of elements. For char v[6], that means $n = 6$, the first index is $0$, and the last valid index is $6-1 = 5$.
Finding the last valid index
An array is declared as char w[10];. What is the last valid index, and is w[10] a valid reference?
- 1Identify the element count
The number in the brackets is 10, so the array has $n = 10$ elements.
- 2Apply the index rule
Valid indices run from $0$ to $n-1$, which is $0$ to $9$.
- 3Test the index in question
The index 10 is greater than 9, so it lies outside the array.
The last valid index is 9, and w[10] is not valid.
Tracing the Pointer Declaration
A pointer is declared in a similar form, but the star symbol does the work that the brackets did for the array. The source reads the star as pointer to. The declaration char *p; therefore creates a pointer variable that is meant to hold the address of an object of type char. The name p does not hold a char itself. It holds the location of a char object somewhere else.
- char: the type of object the address should refer to
- *: pointer to
- p: the name of the pointer variable
The diagram shows the relationship. The pointer p stores an address, and that address refers to one object elsewhere. The source says a pointer variable can hold the address of an object of the appropriate type. The type in the declaration tells you what kind of object the address is supposed to point to. A pointer declared as char * is meant for objects of type char, and not for objects of some other type.
Brackets Versus Star
The two declarations use nearly the same pattern, and that is why they are easy to confuse. The difference lies in what each declaration says about the name. The array declaration says the name is a collection of six values. The pointer declaration says the name holds the location of one object of the given type. Reading the symbol is the key step: brackets signal array of, and the star signals pointer to.
| Feature | char v[6]; | char *p; |
|---|---|---|
| Symbol meaning | [ ] means array of | * means pointer to |
| What the name refers to | A collection of six char elements | The address of one char object |
| What is created | Six slots, indexed v[0] to v[5] | A variable meant to hold an address |
| Indexing or dereferencing | Use v[0] through v[5] | Holds an address of an object of type char |
Comparing the array and pointer declarations
When you read any declaration, first find the symbol that changes the meaning of the name. If you see brackets, ask how many elements the collection holds. If you see a star, ask what type of object the address should refer to.
Common Mistakes With Arrays and Pointers
Common mistake Assuming the first index is 1
What it looks likeReading char v[6]; and expecting v[1] to be the first element.
Why it failsEvery array starts at index 0, which is its lower bound. The first valid index is not 1.
Do this insteadRead v[0] as the first element and v[5] as the last.
Common mistake Taking the array size as the last index
What it looks likeBelieving char v[6]; makes v[6] a valid element.
Why it failsValid indices for size n run from 0 to n-1. Index 6 lies outside v.
Do this insteadCompute the last valid index as n-1, which is 5 for six elements.
Common mistake Treating a pointer as if it holds a value of its type
What it looks likeReading char *p; as if p itself were a char.
Why it failsThe star means pointer to. The pointer variable holds the address of a char object, not the char itself.
Do this insteadThink of p as holding a location, and the char object as the thing it refers to.
Common mistake Reading the brackets and star as interchangeable symbols
Practice Reading Declarations
For the declaration int scores[5]; state the element count, the first valid index, and the last valid index. Then say whether a pointer declared as int *q; is an array or a pointer, and what type of object it is meant to refer to.
Hints
- The number in the brackets gives the element count.
- Valid indices run from 0 to n-1.
- The star means pointer to, so q holds an address of an int object.
Key Takeaways
- In a declaration, [ ] means array of and * means pointer to, so the symbol tells you what kind of thing the name is.
- The declaration char v[6]; creates six char elements, indexed from v[0] to v[5].
- Every array starts at index 0, so the valid indices for an array of size n run from 0 to n-1.
- The declaration char *p; creates a pointer variable meant to hold the address of one object of type char, not the value itself.
- The declared type tells you what kind of object a pointer is meant to refer to, so read the type alongside the symbol.