Back to C Programming
2026-07-156 min read

C - Memory Address

Learn C - Memory Address step by step with clear examples and exercises.

Why This Matters

Understanding memory addresses in C is crucial for several reasons:

  1. Debugging: Knowing how to navigate memory addresses can help you locate and fix bugs that might be difficult to find otherwise.
  2. Performance Optimization: By manipulating memory directly, you can optimize your programs for better performance.
  3. Real-world Programming: Many system programming tasks require a deep understanding of memory management, including device drivers, operating systems, and network programming.
  4. Interviews and Exams: Familiarity with C memory addresses is often tested in job interviews and competitive programming contests.
  5. Memory Leaks and Security Vulnerabilities: Understanding memory addresses can help you avoid common errors like memory leaks and buffer overflows, which can lead to security vulnerabilities.

Prerequisites

Before diving into the core concept, make sure you have a good understanding of:

  1. Basic C syntax, including variables, data types, operators, and control structures.
  2. File I/O using standard libraries like stdio.h.
  3. Pointers in C, as they are closely related to memory addresses.
  4. Understanding the difference between stack and heap memory.
  5. Basic knowledge of Assembly language (optional but helpful for a deeper understanding).

Core Concept

In this section, we'll explore how C stores variables in memory and how you can access their addresses using pointers.

Variables and Memory Addresses

When a C program is compiled, all variables are allocated memory in the computer's RAM (Random Access Memory). Each variable has a unique memory address where its value is stored. The sizeof operator can be used to find the size of a variable in bytes.

#include <stdio.h>

int main() {
int num = 42;
printf("The memory address of num is: %p\n", &num);
printf("The size of num is: %zu bytes.\n", sizeof(num));

char ch = 'A';
printf("The memory address of ch is: %p\n", &ch);
printf("The size of ch is: %zu bytes.\n", sizeof(ch));

return 0;
}

In the above example, &num returns the memory address of the variable num. The %p format specifier in printf() is used to print the memory address. Similarly, &ch returns the memory address of the character variable ch.

Pointers and Memory Addresses

A pointer is a variable that stores the memory address of another variable. In C, pointers are declared using the asterisk (*) symbol. To access the value stored at a memory address, you can dereference a pointer using the indirection operator (*).

#include <stdio.h>

int main() {
int num = 42;
int *ptr = &num; // ptr now stores the memory address of num

printf("The value stored at the memory address %p is: %d\n", ptr, *ptr);

char ch = 'A';
char *chrPtr = &ch; // chrPtr now stores the memory address of ch

printf("The character stored at the memory address %p is: %c\n", chrPtr, *chrPtr);

return 0;
}

In this example, ptr is a pointer to an integer. The statement int *ptr = &num; assigns the memory address of num to ptr. Dereferencing ptr using *ptr returns the value stored at that memory address (which is 42 in this case). Similarly, chrPtr is a pointer to a character, and dereferencing it returns the character stored at its memory address (which is 'A' in this case).

Array Memory Addresses

Arrays are a special case in C, as they are essentially contiguous blocks of memory. The first element of an array has the lowest memory address, and each subsequent element has a higher memory address. To access the memory address of an array element, you can use pointer arithmetic.

#include <stdio.h>

int main() {
int arr[5] = {1, 2, 3, 4, 5};
printf("The memory address of the first element of arr is: %p\n", &arr[0]);
printf("The memory address of the second element of arr is: %p\n", &arr[1]);
printf("The value stored at the memory address %p is: %d\n", &arr[1], arr[1]);

return 0;
}

In this example, &arr[0] returns the memory address of the first element in the array arr. &arr[1] returns the memory address of the second element. &arr[1] and arr[1] have different types (pointer to an integer and integer, respectively), but they can still be used interchangeably because they refer to the same memory location.

Worked Example

Let's create a simple program that reads an integer from the user and finds its memory address using a pointer.

#include <stdio.h>

int main() {
int num;
printf("Enter an integer: ");
scanf("%d", &num);

int *ptr = &num;
printf("The memory address of the number you entered is: %p\n", ptr);

return 0;
}

When you run this program, it will prompt you to enter an integer. After entering a number, it will print the memory address where that number is stored.

Common Mistakes

  1. Forgetting the & operator: When using pointers, remember to use the & operator to get the memory address of a variable.
  2. Incorrect pointer arithmetic: Be careful with pointer arithmetic, as it can lead to undefined behavior if you go out of bounds.
  3. Dereferencing uninitialized pointers: Always initialize your pointers before dereferencing them to avoid segmentation faults.
  4. Misunderstanding array memory addresses: Remember that arrays are contiguous blocks of memory, and each element has a higher memory address than the previous one.
  5. Not freeing memory allocated with malloc(): If you allocate memory dynamically using malloc(), don't forget to free it when you're done to prevent memory leaks.
  6. Using pointers for simple tasks: While pointers are powerful, they can also make code more complex and harder to understand. Use them judiciously and avoid overcomplicating your code.

Practice Questions

  1. Write a program that finds the sum of all elements in an array using pointers.
  2. Write a program that sorts an array of integers using bubble sort with pointer arithmetic.
  3. Write a program that swaps two variables using pointers without creating temporary variables.
  4. Write a program that dynamically allocates memory for an array, fills it with user input, and then frees the memory when done.
  5. Write a program that implements a simple linked list data structure using pointers.
  6. Write a program that implements a simple dynamic memory allocation function using malloc() and free().
  7. Write a program that implements a simple heap sort algorithm using pointer arithmetic.
  8. Write a program that demonstrates the difference between stack and heap memory by allocating memory in both and comparing their behavior.

FAQ

  1. Why do we use pointers for memory addresses in C?

Pointers provide a flexible and efficient way to manipulate memory directly, which is essential for many low-level programming tasks. They also allow for dynamic memory allocation and help optimize code by reducing the need for temporary variables.

  1. How does the compiler determine the memory address of a variable?

The compiler assigns memory addresses during the linking phase based on the order of declaration and data type size. However, you can still access variables in any order using pointers.

  1. Can I access memory addresses outside the allocated memory block in C?

Accessing memory addresses outside the allocated memory block is undefined behavior and can lead to unexpected results, including crashes or security vulnerabilities.

  1. What happens if I try to modify a constant variable through a pointer?

Trying to modify a constant variable through a pointer will result in a compile-time error, as the variable is marked as const and cannot be modified.

  1. How can I determine the memory address of a function in C?

The memory address of a function can be determined using the address-of operator (&) just like any other variable. However, functions are called indirectly through a jump instruction, so they are not directly accessible as data like variables.

  1. What is the difference between stack and heap memory in C?

Stack memory is automatically managed by the compiler and is used for local variables, function parameters, and return addresses. Heap memory is dynamically allocated using functions like malloc() and calloc(), and it is typically used for large data structures or dynamic memory allocation.

  1. What are some common pitfalls when working with pointers in C?

Common pitfalls include forgetting to initialize pointers, dereferencing uninitialized pointers, going out of bounds with pointer arithmetic, and leaking memory by failing to free dynamically allocated memory. It's also important to be mindful of the order of operations when using pointers in expressions.