ProgrammingBackend Developer (C)

How do dereference and address-of operators work in the C language, and what nuances do they have when working with pointers to different types?

Pass interviews with Hintsage AI assistant

Answer.

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:

  • Correct matching of pointer types and memory zones.
  • Safe handling of addresses of automatic, static, and dynamic objects.
  • Difference between dereferencing a single pointer and an array of pointers.

Tricky questions.

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 }

Common mistakes and anti-patterns

  • Dereferencing an uninitialized/freed pointer
  • Violating type consistency when casting a pointer
  • Taking the address of a local variable and returning from a function

Real-life example

Negative case

A developer takes the address of a local variable in a function, returns it, and then dereferences the pointer in the calling code.

Pros:

  • The code looks concise, without malloc/free

Cons:

  • Once out of the function, the memory may be overwritten by anything, the result is unpredictable — leading to dangling pointers

Positive case

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:

  • Long-term validity of the pointer
  • Predictability and safety of the code

Cons:

  • The necessity to explicitly free memory using free