Skip to main content

Pointers in C: Address, Dereferencing, * and & 📍

Pointers in C: Address, Dereferencing, * and & is a core C concept covering master C pointers from scratch. Learn memory addresses, the address-of operator (&) and dereference operator (*), declaration, assignments, and NULL and void pointers. This topic is essential for academic learning, board exam preparation, and developing optimized real-world code.

Mentor's Note: Think of your computer's RAM as a massive hotel. Every hotel room has a unique Room Number (Memory Address) and a Guest inside (the value/data). A pointer is simply a card that has a room number written on it! It doesn't contain the guest; it tells you exactly where the guest is staying. Master this mental model, and you've mastered pointers! 💡

📚 Educational Content: Pointers are the heart of C programming and represent a highly weighted topic in GSEB Std 11/12 and university examinations. Understanding the symbols * (value-at-address) and & (address-of) is critical for scoring well in short-answer and output tracing questions.

What You'll Learn

By the end of this tutorial, you'll know:

  • What memory addresses are and how C variables reside in RAM.
  • The difference between the address-of (&) and value-at-address (*) operators.
  • How to declare, initialize, and use pointers to manipulate variables.
  • The definition and practical applications of NULL and void pointers.
  • Why pointers are essential for professional software development.

🌟 The Scenario: The Safe Deposit Box

Imagine a bank with row after row of safe deposit boxes:

  • The Box is the variable.
  • The Box Number (e.g., Box #1024) is the Memory Address.
  • The Gold Bar inside the box is the Value stored in the variable.
  • The Key Tag with the text "Box #1024" written on it is the Pointer.

If you want the gold, you can:

  1. Access the box directly by name (using the variable).
  2. Look at your key tag, read the box address, and unlock that specific box to access the contents (dereferencing the pointer).

📖 Concept Explanation

When you declare a variable in C (e.g., int age = 16;), the compiler automatically assigns it a specific physical location in the computer's memory (RAM).

1. The Address-of Operator (&)

To find out where a variable is located in RAM, you use the address-of operator &. It retrieves the memory location of a variable.

int age = 16;
printf("Address of age is: %p", &age); // Prints address in hexadecimal format (e.g., 0x7ffd23)

2. Declaring Pointers (*)

A pointer is a variable that stores the memory address of another variable. To declare a pointer, use the asterisk * symbol between the data type and the pointer variable name.

int *ptr; // ptr is a pointer that can hold the address of an integer variable

3. Pointer Assignment

To make a pointer point to a variable, assign the address of the variable using the & operator:

int age = 16;
int *ptr;
ptr = &age; // ptr now stores the address of age

4. Dereferencing Pointers (*)

To read or modify the value stored at the address a pointer is pointing to, use the value-at-address operator *. This operation is called dereferencing.

printf("Value at address: %d", *ptr); // Prints 16
*ptr = 20; // Modifies the value of 'age' directly in memory to 20
printf("New age: %d", age); // Prints 20

📦 Special Pointers: NULL and void*

The NULL Pointer

A NULL pointer is a pointer that points to nothing (explicitly set to address 0).

Always Initialize to NULL

If you declare a pointer but don't assign it an address immediately, it will point to a random, garbage location in memory (a wild pointer). If you dereference it, your program will crash. Always initialize unassigned pointers to NULL.

int *ptr = NULL;

The void Pointer (void*)

A void pointer is a generic pointer. It can store the address of any data type (int, float, char, etc.). However, because it has no associated data type, you cannot dereference it directly. You must first cast it to a specific pointer type.

int x = 10;
void *gptr = &x; // Allowed!
// printf("%d", *gptr); // Error! Cannot dereference void pointer directly
printf("%d", *(int*)gptr); // Correct! Cast to (int*) first, then dereference

🧠 Why Are Pointers Useful?

Pointers are not just a syntax quirk; they are critical because they:

  1. Enable Pass-by-Reference: Let functions modify caller variables directly.
  2. Optimize Performance: Avoid copying large structures or arrays in memory.
  3. Allow Dynamic Memory Allocation: Enable booking memory during program runtime.
  4. Interface with Hardware: Permit direct access to registers and system components in embedded programming.

🧠 Algorithm & Step-by-Step Logic

Tracing the relationship between variables and pointers:

  1. Start 🏁
  2. Create variable x = 5.
  3. Create pointer ptr and store the address of x inside it.
  4. Read the value of x directly.
  5. Modify the value of x by writing *ptr = 100.
  6. Read the new value of x and verify it has changed to 100.
  7. End 🏁

💻 Implementation (C99)

This program shows pointer declarations, assignments, dereferencing, void pointer usage, and NULL safety checks.

#include <stdio.h>

// 🛒 Scenario: Variable Inspector
// 🚀 Action: Demonstrate memory addresses, dereferencing, and void pointer casting

int main() {
int score = 95;
double temperature = 98.6;

// 1. Pointer Declarations & Assignments
int *score_ptr = &score;
double *temp_ptr = &temperature;

// 2. Displaying Addresses and Values
printf("1. score variable:\n");
printf(" Value of score: %d\n", score);
printf(" Address of score (&score): %p\n", (void*)&score);
printf(" Value stored in score_ptr: %p\n", (void*)score_ptr);
printf(" Value of score via pointer dereference (*score_ptr): %d\n\n", *score_ptr);

// 3. Modifying memory directly using pointers
*score_ptr = 99; // Change the value of score via the pointer
printf("2. After modifying memory using *score_ptr = 99:\n");
printf(" New value of score: %d\n\n", score);

// 4. Working with NULL pointers
int *uninitialized_ptr = NULL;
printf("3. NULL Pointer check:\n");
if (uninitialized_ptr == NULL) {
printf(" uninitialized_ptr is safe (pointing to NULL).\n\n");
}

// 5. Working with Void Pointers (Generic Pointers)
void *generic_ptr = &temperature;
printf("4. Generic void pointer usage:\n");
printf(" Address stored in generic_ptr: %p\n", generic_ptr);
// Cast generic_ptr to double* to dereference it safely
printf(" Value via typecasted double* pointer: %.1f\n", *(double*)generic_ptr);

return 0;
}

// Output:
// 1. score variable:
// Value of score: 95
// Address of score (&score): 0x7ffe3fb44e54
// Value stored in score_ptr: 0x7ffe3fb44e54
// Value of score via pointer dereference (*score_ptr): 95
//
// 2. After modifying memory using *score_ptr = 99:
// New value of score: 99
//
// 3. NULL Pointer check:
// uninitialized_ptr is safe (pointing to NULL).
//
// 4. Generic void pointer usage:
// Address stored in generic_ptr: 0x7ffe3fb44e58
// Value via typecasted double* pointer: 98.6

📊 Sample Dry Run

Let's trace the values of variables and memory addresses step-by-step: Assume variable score is placed at memory address 0x1000.

StepInstructionscore Valuescore_ptr Value (Address)*score_ptr ValueDescription
1int score = 95;95GarbageUndefinedscore initialized in memory.
2int *score_ptr = &score;950x100095score_ptr stores address of score.
3*score_ptr = 99;990x100099Memory at address 0x1000 updated.

📉 Complexity Analysis

Time Complexity ⏱️

  • Pointer Access / Modification: $O(1)$ time. Accessing memory through addresses is supported directly by hardware and runs instantly with zero CPU cycle overhead.

Space Complexity 💾

  • Auxiliary Space: $O(1)$ auxiliary space. A pointer variable requires a small, fixed size in memory (typically 4 bytes on a 32-bit system, or 8 bytes on a 64-bit system) regardless of the size of data it points to.

🎨 Visual Logic & Diagrams

The following block diagram visualizes how pointers store addresses to reference targets:


🎯 Practice Problems

Easy Level 🟢

  • Problem 1: Write a program to declare an integer variable, a float variable, and a char variable, and print their values using their respective pointers.
  • Problem 2: Print the memory addresses of two separate double variables to verify how many bytes apart they are stored.

Medium Level 🟡

  • Problem 3: Write a C function that swaps the values of two variables. Pass their addresses using pointers to ensure the swap affects the original variables.
  • Problem 4: Declare a void* pointer, assign a character variable to it, and print the character by casting it properly.

Hard Level 🔴

  • Problem 5: Create a pointer tracer simulator. Declare a variable x. Create a pointer ptr1 pointing to x. Create a second pointer ptr2 pointing to the address of ptr1. Modify x by dereferencing ptr2 twice (**ptr2 = 250). Trace the states of all variables.

❓ Frequently Asked Questions

Q: What is the difference between * and & in C?

& is the Address-of operator. It finds the memory location of an existing variable. * is used in two contexts: (1) to declare pointer variables, and (2) as the Dereference operator to retrieve or modify the value at a pointer's address.

Q: What happens if I dereference a pointer that is set to NULL?

Dereferencing a NULL pointer causes a Segmentation Fault or a runtime crash because you are asking the CPU to read memory address 0, which is reserved by the operating system and is not accessible by user programs.

Q: How big is a pointer variable in memory?

The size of a pointer is independent of the data type it points to. It depends solely on the architecture of the system. On a 64-bit CPU, all pointers (int*, double*, char*) take 8 bytes. On a 32-bit CPU, they take 4 bytes.


✅ Summary

In this tutorial, you've learned:

  • ✅ Variables are stored in memory at unique hexadecimal addresses.
  • ✅ The & operator fetches the address; the * operator accesses the value at that address.
  • ✅ Pointers must be initialized to NULL to prevent wild pointer bugs.
  • ✅ A void* pointer is generic and must be typecast before it can be dereferenced.
  • ✅ Modifying a dereferenced pointer directly alters the underlying variable's value.

💡 Interview Tips & Board Focus 👔

Common Questions

  • "What is a wild pointer, and how do you prevent it?"
  • "What is the size of a character pointer vs an integer pointer?"
  • "Explain dereferencing in simple terms."

Answering Strategy

  • Always clarify that pointer size is determined by system architecture (32-bit vs 64-bit), not by data types. This is a common trick question!
  • Write pointers with spaces clearly to avoid mistakes in exam answers. Both int* ptr and int *ptr are valid, but int *ptr is the industry standard format.

📚 Best Practices & Common Mistakes

✅ Best Practices

  • Check if a pointer is NULL before performing dereference operations.
  • Use the suffix _ptr or p in your variable names (e.g. val_ptr, p_count) to make code readable.
  • Match data types accurately: do not point an int* pointer to a float variable.

❌ Common Mistakes ⚠️

  • Dereferencing uninitialized pointers: Writing int *p; *p = 50; without assigning an address like p = &var; first.
  • Mismatching assignments: Writing ptr = x; (assigning value) instead of ptr = &x; (assigning address).
  • Incorrect dereferencing sequence: Writing ptr instead of *ptr when trying to print or modify values.

📚 Further Reading

Continue your learning path:


Guide Version: 2.0
Purpose: Educational content creation standards for VD Computer Tuition


---

📍 Visit Us

🏫 VD Computer Tuition Surat

VD Computer Tuition
📍 Address
2/66 Faram Street, Rustompura
Surat395002, Gujarat, India
📞 Phone / WhatsApp
+91 84604 41384
🌐 Website

Computer Classes & Tuition — Areas We Serve in Surat

AdajanAlthanAmroliAthwaAthwalinesBhagalBhatarBhestanCanal RoadChowkCitylightDumasGaurav PathGhod Dod RoadHaziraJahangirpuraKamrejKapodraKatargamLimbayatMagdallaMajura GateMota VarachhaNanpuraNew CitylightOlpadPalPandesaraParle PointPiplodPunaRanderRing RoadRustampuraSachinSalabatpuraSarthanaSosyo CircleUdhnaVarachhaVed RoadVesuVIP Road
📞 Call Sir💬 WhatsApp Sir