Declaration & Dereferencing
Working with pointers day to day comes down to three operators: declaring a pointer variable, using & to find an address, and using * to follow (dereference) that address back to a value. This page walks through all three carefully, because the two different jobs that * does are one of the most common early stumbling blocks in C.
Declaring a pointer
A pointer declaration looks like a normal variable declaration with an extra * in front of the name:
int *p; // p is a pointer to an int double *dp; // dp is a pointer to a double char *cp; // cp is a pointer to a char
The type before the * (int, double, char, ...) is the type of thing the pointer will point to — it tells the compiler how many bytes to read or write when the pointer is dereferenced, and how to interpret those bytes. p itself is not an int; it is a variable that holds the address of an int.
The address-of operator, &
To make a pointer actually point at something, you need that something's address. The & operator, applied to a variable, produces its address:
#include <stdio.h>
int main(void) {
int score = 95;
int *p = &score; // p now holds the address of score
printf("score = %d\n", score);
printf("&score = %p\n", (void *)&score);
printf("p = %p\n", (void *)p);
return 0;
}score = 95 &score = 0x7ffe4a2b3c1c p = 0x7ffe4a2b3c1c
Notice that p and &score print the same address — that is exactly what it means for p to "point to" score.
Dereferencing with *
Once a pointer holds a valid address, *p lets you read or write the value stored there, as if you had used the original variable's name directly:
#include <stdio.h>
int main(void) {
int score = 95;
int *p = &score;
printf("*p before = %d\n", *p); // reads score through p
*p = 100; // writes through p, which changes score
printf("score after *p = 100: %d\n", score);
return 0;
}*p before = 95 score after *p = 100: 100
*p = 100; does not change what p points to — it changes the value stored at the address p already holds. That is the whole mechanism that lets a function modify a caller's variable through a pointer parameter, which is covered in detail later in this section.
Uninitialized pointers are dangerous
int *p; // WRONG: p holds garbage, do not dereference it int *q = NULL; // OK: q clearly points to nothing yet int value = 42; int *r = &value; // OK: r points to a real, valid address
Putting it together
int *p;declares —*here is part of the type, meaning "pointer to int".&xtakes the address ofx.*pdereferencesp— follows the address to read or write the value there.An uninitialized pointer must be set to a real address or
NULLbefore it is ever dereferenced.