The dereference operator * and the address-of operator & are among the fundamental tools for memory management in C. They allow direct control over data in memory, which has made C a popular language for systems programming.
Background:
Since the advent of the C language (in the 1970s), its philosophy has been closely tied to low-level memory management. The * and & operators implement indirect addressing techniques utilized at the processor level, enabling work with pointers, dynamic memory allocation, and the creation of efficient data structures.
Problem: Errors in using these operators lead to numerous bugs: memory leaks, data corruption, segmentation faults. The compiler does not always explicitly signal these errors, especially if pointer types match in size but differ in content.
Solution: Pay careful attention to the pointer type, track the lifecycle of allocated memory, perform initialization and correct deallocation, and check the validity of dereference operations and addresses used.
Example code:
int x = 10; int *p = &x; // address-of operator int y = *p; // dereference (getting value from the address) // Working with a pointer to an array int arr[3] = {1,2,3}; int *pa = arr; printf("%d", *(pa+1)); // second element of the array
Key features:
Can you take the address of a temporary variable, for example: & (x + y)?
No, you cannot take the address of an expression because the result of the expression is not a memory object. You can only take the address of a variable, array, or structure.
Example code:
int z = 5; int p = &(z + 1); // Compilation error
What is the difference when dereferencing a void pointer?
A pointer of type void * cannot be dereferenced directly until it is cast to a specific type. It is a generic pointer, but dereference operations are type-independent only after an explicit cast:
void *pv = &x; int value = *(int*)pv; // OK
Can you dereference a null pointer (NULL)?
No, this leads to undefined behavior — memory corruption or program termination. Always check the pointer before dereferencing:
int *ptr = NULL; if (ptr) { *ptr = 10; // Will never execute }
A developer takes the address of a local variable in a function, returns it, and then dereferences the pointer in the calling code.
Pros:
Cons:
Dynamic memory allocation is used for the variable, the address is returned to the calling code, and in the end, it's freed using free.
Pros:
Cons: