Section 9 : Pointers
Pointers are a type of variable in C++. They are variables used for storing the address of data.
We have 2 types of variables:
* Data variables: Used for storing data.
* Example: int x = 10;
* Address variables: Used for storing addresses.
* Example: int *p; p = &x;
Basic Syntax
int x = 10;
int *p; // Declaration
p = &x; // Initialization
cout << *p; // Dereferencing (Accessing the value at the address)
Memory Visualization:
graph TD
subgraph Memory
direction BT
x_node[("Variable: x <br/> Address: 200 <br/> Value: 10")]
p_node[("Variable: p <br/> Address: 300 <br/> Value: 200")]
p_node -->|Points to| x_node
end
style x_node fill:#f9f,stroke:#333,stroke-width:2px
style p_node fill:#bbf,stroke:#333,stroke-width:2px
Why Pointers?
A program can only access the Code section and Stack directly. Pointers help it to access the Heap section. A pointer variable exists in the Stack, but the address it stores points to the Heap. Thus, it indirectly helps us access the Heap section.
Main Uses: * To access Heap memory. * To access files using file pointers. * To access network connections. * To access hardware devices (keyboard, mouse, printer, etc.).
Note: In Java and C#, there are no pointers exposed to the programmer. Therefore, we cannot access devices directly through programs; we can only access them using the JVM or through the Common Language Runtime (CLR). Consequently, System Programming is generally not done in Java or C#.
Heap Memory
- Dynamic Memory: Memory decided at run time, not compile time.
- Uses the
newkeyword; memory is created in the Heap. - Heap memory does not delete automatically until the program is over or manually freed.
Stack vs Heap Visualization:
graph LR
subgraph "Stack (Static Memory)"
main[main function]
ptr["int *p"]
end
subgraph "Heap (Dynamic Memory)"
arr["[ int ][ int ][ int ][ int ][ int ]"]
end
main -- contains --> ptr
ptr -- points to --> arr
Memory Leak
When we create memory using new and point to it with a pointer p, if we subsequently set p to NULL without freeing the memory, we lose access to that Heap memory. This is a Memory Leak. Therefore, we must free the memory first.
Null Pointer
A pointer pointing to nothing (valid address 0).
* p = NULL; or p = nullptr;
Pointer Arithmetic
Pointer arithmetic depends on the data type of the pointer.
* int is usually 4 bytes. If p is an integer pointer (int *p), p++ moves the address forward by 4 bytes.
* char is 1 byte. If p is a char pointer, p++ moves the address forward by 1 byte.
Example Calculation:
int A[] = {2, 4, 6, 8, 10};
int *p = A; // p points to A[0] (Value: 2)
int *q = &A[3]; // q points to A[3] (Value: 8)
// Operations
p++; // Moves to next index
p--; // Moves back
p = p + 2; // Moves forward 2 indices
p = p - 2; // Moves backward 2 indices
int d = q - p; // Returns the distance (number of elements) between pointers
Problems with Pointers
- Uninitialized Pointer:
- Created a pointer
int *p;and then assigned*p = 25;withoutppointing to a valid address. This causes undefined behavior.
- Created a pointer
- Memory Leak:
- Not deleting memory before setting the pointer to null.
- Note:
NULL=0.nullptris recommended in modern C++ as it is type-safe.
- Dangling Pointer:
- A pointer pointing to a location that does not exist or has been deleted/deallocated.
Dangling Pointer Example:
void main() {
int *p = new int[5];
// ... code ...
delete []p;
// p is now a Dangling Pointer here
cout << *p; // Error or garbage value
}
References
- A Reference is nothing but an alias/nickname of a variable.
- References do not consume extra memory (conceptually, they share the memory of the original variable).
- Rules:
- Declaration of a reference variable requires an initializer immediately.
int &y = x;(Correct)int &y;(Error: not possible)
- We cannot change the reference to refer to another variable later.
- If
int &y = x;is done,yis locked tox. - Writing
y = a;will assign the value ofatox(viay), it will not makeyreferencea.
- If
- Declaration of a reference variable requires an initializer immediately.
Reference Visualization:
graph TD
subgraph Memory
box[("Variable Address: 200 <br/> Name: x <br/> Alias: y <br/> Value: 10")]
end
style box fill:#fff,stroke:#333,stroke-width:2px,stroke-dasharray: 5 5
Additional Examples & Notes
1. Pointer Size
- The size of a pointer variable is generally independent of its data type.
int *p1,float *p2,char *p3— all take 8 bytes in modern 64-bit compilers (or 4 bytes in 32-bit).
2. Negative Indexing
int A[] = {2, 4, 6, 8, 10, 12};
int *p = &A[3]; // p points to index 3 (Value 8)
cout << p[-2];
// p[-2] means go 2 integers backward from current p.
// Current: Index 3. Back 2: Index 1.
// A[1] is 4. Result: 4.
3. Reference Logic
int x = 10;
int &y = x; // y is alias of x
y = x + y; // y = 10 + 10 = 20.
cout << x; // Since y changed to 20, x is also 20.