Pointers in C: when to use the ampersand and the asterisk?

Learn pointers in c: when to use the ampersand and the asterisk? with practical examples, diagrams, and best practices. Covers c, pointers development techniques with visual explanations.

Pointers in C: Demystifying Ampersand (&) and Asterisk (*)

Hero image for Pointers in C: when to use the ampersand and the asterisk?

Understand the fundamental roles of the ampersand (&) and asterisk (*) operators in C programming for effective pointer manipulation.

Pointers are a cornerstone of C programming, offering powerful capabilities for direct memory access and manipulation. However, their syntax, particularly the use of the ampersand (&) and asterisk (*) operators, often causes confusion for beginners. This article aims to clarify the distinct functions of these operators, providing a solid foundation for working with pointers in C.

The Address-Of Operator: Ampersand (&)

The ampersand symbol (&), when placed before a variable name, is known as the 'address-of' operator. Its primary function is to return the memory address where a variable is stored. In essence, it tells you "where" in memory a particular piece of data resides. This address is what a pointer variable holds.

#include <stdio.h>

int main() {
    int num = 10;
    printf("Value of num: %d\n", num);
    printf("Address of num: %p\n", &num); // Using & to get the address
    return 0;
}

Using the & operator to retrieve the memory address of a variable.

The Dereference Operator: Asterisk (*)

The asterisk symbol (*) has two main uses related to pointers: declaration and dereferencing. When used in a variable declaration, it signifies that the variable is a pointer. For example, int *ptr; declares ptr as a pointer to an integer. When used with an already declared pointer variable, it acts as the 'dereference' operator. Dereferencing means accessing the value stored at the memory address that the pointer holds. It essentially answers the question: "What value is at this address?"

#include <stdio.h>

int main() {
    int num = 25;
    int *ptr; // Declaring ptr as a pointer to an int

    ptr = &num; // ptr now holds the address of num

    printf("Value of num: %d\n", num);
    printf("Address of num: %p\n", &num);
    printf("Value of ptr (address it holds): %p\n", ptr);
    printf("Value at the address ptr holds (*ptr): %d\n", *ptr); // Dereferencing ptr

    *ptr = 50; // Changing the value at the address ptr holds
    printf("New value of num after dereferencing: %d\n", num);

    return 0;
}

Demonstrating pointer declaration, assignment, and dereferencing with *.

flowchart TD
    A[Variable 'num' = 10] --> B("Memory Location (e.g., 0x7ffe...)")
    B -- "&num" --> C[Address of 'num']
    C -- "ptr = &num" --> D[Pointer 'ptr' holds address of 'num']
    D -- "*ptr" --> B
    B -- "Value at address" --> E[Value of 'num' (10)]

Flowchart illustrating the relationship between a variable, its address, a pointer, and dereferencing.

Summary of Ampersand (&) vs. Asterisk (*)

To summarize, the ampersand (&) gives you the address of a variable, while the asterisk (*) is used to declare a pointer and to access the value stored at the address a pointer holds. They are inverse operations: & gets the address, * gets the value at an address. Understanding this distinction is crucial for correctly manipulating memory and building robust C applications.