Skip to Content
Course content

46: Pointers and Arrays

Click on the "Edit" button in the top corner of the screen to edit your slide content.

I've always found that the relationship between pointers and arrays is where a lot of C learners hit a wall. It's usually because textbooks try to explain it as a set of rigid rules. Instead, let's just open up a file, write some code, and see how the compiler actually treats these things. I want to figure out exactly what happens when we use an array name in different contexts.

Looking at the raw memory

Let's start with something simple. I'll create a small array of high scores for a game we're pretending to build. I want to see where these scores actually live in memory.

int scores[] = {1200, 4500, 3100, 800, 9200};
printf("Array address: %p\n", (void*)scores);
printf("First element address: %p\n", (void*)&scores[0]);

When I run this, I notice something immediately: the addresses are identical. Exactly the same. Now, that's interesting. In my head, scores is the "whole array" and &scores[0] is just the "first item." But to the C compiler, the name of the array—when used in most expressions—is essentially just a pointer to the first element. It "decays" into a pointer.

Pushing the boundaries of the index

Since the array name is basically a pointer, I wonder if I can treat it like one. Normally, we use scores[1] to get the second score. But if scores is a pointer, I should be able to use pointer arithmetic.

Let's try this:

int *ptr = scores; 
printf("Second score via index: %d\n", scores[1]);
printf("Second score via pointer: %d\n", *(ptr + 1));

Both print 4500. It works. But here is the part that always tripped me up when I first started: scores[1] is actually just "syntactic sugar." Under the hood, the compiler converts scores[i] into *(scores + i). They are literally the same operation. The brackets are just there because humans find them easier to read than dereferencing parentheses.

Passing the torch to a function

Now, here is where things get messy. I want to write a function that prints these scores. I'll try to pass the array in. But wait—C doesn't actually let you pass an entire array by value. It would be incredibly inefficient to copy 1,000 integers every time you called a function.

Let's see what happens when I try to define the function in two different ways:

void printScores(int arr[]) {
    printf("Address inside: %p\n", (void*)arr);
}

// Versus

void printScores(int *arr) {
    printf("Address inside: %p\n", (void*)arr);
}

If you compile this, you'll realize something surprising: these two function signatures are identical to the compiler. When you put int arr[] in a function parameter list, C silently converts it to int *arr. It doesn't matter how you write it; you're just passing a pointer to the first element of the array.

This is why you almost always see a second argument like int size passed along with arrays. Since the function only receives a pointer, it has no clue how large the original array was. It just sees a memory address and hopes you don't tell it to read past the end of the allocated space. If you do, you're in "Undefined Behavior" territory, which is a fancy way of saying your program might crash or, worse, silently corrupt your data.

The one exception

I should mention one weird quirk I stumbled upon. I mentioned that the array name decays to a pointer, but there is one place it doesn't: the sizeof operator.

printf("Size of array: %zu\n", sizeof(scores));
printf("Size of pointer: %zu\n", sizeof(&scores[0]));

The first one gives me the size of the entire block (5 integers * 4 bytes = 20 bytes). The second one gives me the size of a single memory address (usually 8 bytes on 64-bit systems). In this specific case, the compiler remembers that scores was declared as an array, not a pointer. It's a helpful exception, but don't rely on it once you've passed that array into a function—once it's inside the function, sizeof will only give you the size of the pointer.




📋 Practical Task

Exercise: High Score Average Calculator

Write a program that manages a list of game scores. You must implement a function called calculate_average that takes an array of integers and its size as arguments. However, there's a catch: inside the calculate_average function, you are not allowed to use square brackets ([]) to access the array elements. You must use pointer arithmetic (e.g., *(ptr + i)) to traverse the array and sum the values.

  • Create an array of at least 5 integers.
  • Pass the array and its size to your function.
  • Calculate the average as a float.
  • Print the final average to the console.
Rating
0 0

There are no comments for now.

to be the first to leave a comment.