Pointer & Access Operators
Pointer and access operators let you work with memory addresses, dereference pointers, and access members of structures and arrays. These operators give you low-level control over data, which is useful for efficient memory use, direct hardware access, and interfacing with libraries.
& (reference / address-of)
The & operator returns the memory address of a variable. In a pointer context, it is called the address-of operator and gives you a pointer to the variable.
void setup() {
Serial.begin(9600);
int x = 42;
int *ptr = &x; // ptr now holds the address of x
Serial.println(x); // prints 42
Serial.println((long)ptr); // prints the memory address (e.g., 2298)
}
void loop() {
// nothing to do here
}
In this example, &x retrieves the address where x is stored in RAM. This address is assigned to the pointer variable ptr. Use the address-of operator when you need to pass a variable by reference to a function or store its location for later access.
* (dereference / pointer)
The * operator accesses the value stored at a memory address held by a pointer. This is called dereferencing. When used in a declaration (int *ptr;), it creates a pointer type.
void setup() {
Serial.begin(9600);
int x = 42;
int *ptr = &x; // ptr points to x
Serial.println(*ptr); // dereference: prints 42
*ptr = 99; // modify x through the pointer
Serial.println(x); // prints 99
}
void loop() {
// nothing to do here
}
In this example, *ptr reads the value at the address stored in ptr, which is the value of x. Writing *ptr = 99 changes x indirectly. Dereferencing is the primary way to read or modify data through a pointer.
. (dot / member access)
The . operator accesses a member of a structure or class directly. It is used when you have the actual struct or object (not a pointer to it).
struct SensorData {
int temperature;
int humidity;
};
void setup() {
Serial.begin(9600);
SensorData data;
data.temperature = 25; // access member with dot
data.humidity = 60;
Serial.print("Temp: ");
Serial.println(data.temperature);
Serial.print("Humidity: ");
Serial.println(data.humidity);
}
void loop() {
// nothing to do here
}
Here, data.temperature and data.humidity access the members of the SensorData struct using the dot operator. The dot operator has the highest precedence among access operators.
-> (arrow / pointer member access)
The -> operator accesses a member of a structure or class through a pointer. It combines dereferencing and member access in one step โ ptr->member is equivalent to (*ptr).member.
struct SensorData {
int temperature;
int humidity;
};
SensorData data;
SensorData *ptr = &data;
void setup() {
Serial.begin(9600);
ptr->temperature = 30; // same as (*ptr).temperature = 30
ptr->humidity = 70;
Serial.print("Temp: ");
Serial.println(ptr->temperature);
Serial.print("Humidity: ");
Serial.println(ptr->humidity);
}
void loop() {
// nothing to do here
}
In this example, ptr->temperature accesses the temperature field of the struct that ptr points to. The arrow operator is cleaner and less error-prone than manually dereferencing with * and then using ..
[] (array subscript)
The [] operator accesses an element of an array by its index. Arrays are zero-indexed, so the first element is at index [0]. The subscript operator is equivalent to pointer arithmetic: array[i] is the same as *(array + i).
void setup() {
Serial.begin(9600);
int readings[5] = {10, 20, 30, 40, 50};
// Access elements with subscript
Serial.println(readings[0]); // first element: 10
Serial.println(readings[2]); // third element: 30
readings[4] = 99; // modify last element
// Loop through array
for (int i = 0; i < 5; i++) {
Serial.print("Index ");
Serial.print(i);
Serial.print(": ");
Serial.println(readings[i]);
}
}
void loop() {
// nothing to do here
}
This example stores five sensor readings in an array and accesses them with the subscript operator. The subscript operator works on any pointer โ not just arrays โ so int *p = readings; p[2] also gives element 30.