Pointer Arithmetic: Moving through Memory
As established, adding 1 to a pointer does not add one byte to the address; it adds one unit of the underlying type.
If p is an int* and an int is 4 bytes:
p + 1 increases the address by 4.
This allows for incredibly efficient iteration over contiguous structures like arrays.
Double Indirection: Pointers to Pointers
In C, we can have pointers that point to other pointers. This is commonly used for:
- Modifying a Pointer in a Function: Since C is pass-by-value, to change which address a pointer points to, you must pass a pointer to that pointer (
int **). - Dynamic 2D Arrays: An array of pointers, where each pointer points to a row.
- Command Line Arguments:
char **argvis an array of strings (where each string ischar*).
int x = 10;
int *p = &x;
int **pp = &p; // pp -> p -> x
printf("%d", **pp); // Output: 10
Function Pointers: Executable Logic as Data
A function’s code resides in memory, just like data. A Function Pointer stores the address of the entry point of a function. This enables Callbacks and higher-order programming in C.
Syntax: Return_Type (*Pointer_Name)(Parameter_Types);
int add(int a, int b) { return a + b; }
// declare a pointer to a function taking two ints and returning one int
int (*operation)(int, int) = add;
int result = operation(5, 3); // result is 8
Generic Pointers: void *
The void * type is a Generic Pointer. It can point to any data type, but it cannot be dereferenced directly because the compiler doesn’t know the size or type of the underlying data.
To use the data, you must “cast” it back to a specific type.
int x = 5;
void *vp = &x;
// printf("%d", *vp); // ERROR: Invalid
printf("%d", *(int*)vp); // Correct: Cast to int* then dereference
Generic Pointers
void *ptr; int x = 10; ptr = &x; // How to read x into 'val'? int val = ;
The Dangers: Aliasing and Dangling Pointers
Pointer Aliasing occurs when two pointers point to the same memory location. This can confuse the compiler’s optimizer unless the restrict keyword is used.
Dangling Pointers are pointers that point to memory that has been freed or is out of scope.
int* get_ptr() {
int x = 10;
return &x; // WARNING: x is on the stack and will be destroyed!
}
Interactive Lab
Waiting for signal...