← Back to quizzesFree quiz

Pointers and Dynamic Memory in C

Understanding pointers and dynamic memory allocation is essential for mastering the C programming language. This course breaks down the fundamental ideas behind pointer dereferencing, memory…

10 questions~5 min
Pointers and Dynamic Memory in C — Qwi
0 / 10
Score: 0%
1

What is the effect of the statement `*p = 20;` after `p` has been assigned the address of `x`?

2

Given `char i = 9, j = 12; char *p1, *p2; p1 = &i; p2 = &j; *p1 = *p2;`, what are the values of `i` and `j` after the assignment?

3

Why must a temporary pointer be used with `realloc` instead of assigning directly to the original pointer?

4

What does the expression `p + 1` compute when `p` is a pointer to `long int` and `&i = 1230`?

5

In the function `void incrementer(int *x) { *x = *x + 1; }`, what is the value of `a` after calling `incrementer(&a);` if `a` was initially 5?

6

What is the primary difference between `malloc` and `calloc` when allocating memory for an array of integers?

7

After executing `free(p); p = NULL;`, what is the state of pointer `p`?

8

Why is it unsafe to call `free(p); *p = 10;` after freeing memory?

9

When passing an array to a function as `void afficher(int t[], int n)`, how does the function receive the array?

10

What is the correct way to access the `reel` field of a structure through a pointer `p`?

Pointers and Dynamic Memory in C: Core Concepts

Understanding pointers and dynamic memory allocation is essential for mastering the C programming language. This course breaks down the fundamental ideas behind pointer dereferencing, memory management functions (malloc, calloc, realloc, and free), and common pitfalls such as dangling pointers. Each section is designed to be SEO‑friendly, using clear headings, keyword‑rich paragraphs, and structured lists to help learners and search engines alike.

1. Pointer Dereferencing and Assignment

When a pointer p holds the address of a variable x, the expression *p refers to the value stored at that address. Assigning to *p directly modifies the original variable.

  • Key point: *p = 20; changes x to 20 because p points to x.
  • Common mistake: Assuming the assignment creates a temporary copy; it does not.

Example:

int x = 5;
int *p = &x;   // p now holds the address of x
*p = 20;        // x becomes 20

2. Copying Values Through Pointers

When two pointers reference distinct variables, dereferencing one and assigning it to the other copies the value, not the address.

  • Given char i = 9, j = 12; and char *p1 = &i, *p2 = &j;, the statement *p1 = *p2; copies the value of j into i.
  • Result: i becomes 12 while j remains 12.

Visual representation:

i (9)  <-- p1 -->  address of i
j (12) <-- p2 -->  address of j
*p1 = *p2   // i now holds 12

3. Safe Use of realloc

The realloc function attempts to resize an existing memory block. If it fails, it returns NULL and leaves the original block untouched. Assigning the result directly to the original pointer can cause loss of the original address, leading to memory leaks.

  • Best practice: Use a temporary pointer.
    int *temp = realloc(original, newSize);
    if (temp) {
        original = temp; // safe replacement
    } else {
        // handle allocation failure, original is still valid
    }
    
  • This pattern ensures that if realloc fails, you still have a valid pointer to free.

4. Pointer Arithmetic

Pointer arithmetic respects the size of the pointed‑to type. Adding 1 to a pointer advances it by sizeof(type) bytes.

  • For a long int pointer p where &i = 1230 (assuming sizeof(long int) = 4), the expression p + 1 yields the address 1234.
  • Remember: the actual numeric result depends on the system’s data model (e.g., 8‑byte long on 64‑bit platforms).

5. Passing Pointers to Functions

Functions can modify variables indirectly by receiving a pointer to the variable.

  • Example function:
    void incrementer(int *x) {
        *x = *x + 1;
    }
    
  • Calling incrementer(&a); when a is initially 5 results in a becoming 6.

6. malloc vs. calloc

Both functions allocate raw memory, but they differ in initialization:

  • malloc allocates the requested number of bytes without initializing them. The memory contains indeterminate (garbage) values.
  • calloc allocates memory for an array and automatically zero‑initializes every byte.
  • Typical usage:
    int *arr1 = malloc(10 * sizeof(int));   // values undefined
    int *arr2 = calloc(10, sizeof(int)); // all elements are 0
    

7. Freeing Memory and Nullifying Pointers

After releasing a memory block with free, the pointer still holds the old address, which is now invalid. Setting the pointer to NULL prevents accidental dereferencing.

  • Correct pattern:
    free(p);
     p = NULL; // p is now a null pointer, safe to test before use
    
  • A null pointer is guaranteed not to point to any valid object, making subsequent checks reliable.

8. Dangling Pointers and Undefined Behavior

Dereferencing a pointer after its memory has been freed leads to undefined behavior because the pointer becomes dangling.

  • Example of unsafe code:
    free(p);
    *p = 10; // undefined behavior – p is dangling
    
  • Always ensure a pointer is either set to NULL or reassigned before further use.

9. Summary of Key Takeaways

  • Dereferencing a pointer (*p) accesses the value at the address stored in p.
  • Pointer arithmetic adds multiples of the pointed‑to type’s size.
  • Use a temporary pointer with realloc to avoid memory leaks.
  • malloc leaves memory uninitialized; calloc zero‑initializes it.
  • Always free allocated memory and set the pointer to NULL to prevent dangling pointers.
  • Passing pointers to functions enables direct modification of variables.

By mastering these concepts, you will write safer, more efficient C programs and avoid common memory‑related bugs that can cause crashes or security vulnerabilities.