Arrays & Pointers
Memory layout and indirection
Introduction
In this lesson, you'll learn about arrays & pointers in C. Coming from JavaScript, you already have a foundation for understanding this concept. We'll build on that knowledge while highlighting the key differences.
In JavaScript, you're familiar with memory layout and indirection.
C has its own approach to memory layout and indirection, which we'll explore step by step.
The C Way
Let's see how C handles this concept. Here's a typical example:
#include <stdlib.h>
#include <string.h>
/* Fixed array */
int nums[5] = {1, 2, 3, 4, 5};
int len = sizeof(nums) / sizeof(nums[0]); /* 5 */
/* Dynamic array */
int *dyn = malloc(10 * sizeof(int));
if (!dyn) { /* handle failure */ }
dyn[0] = 1;
dyn = realloc(dyn, 20 * sizeof(int));
free(dyn); /* must free! */
/* Arrays decay to pointers — always pass length */
void fill(int *arr, int len, int val) {
for (int i = 0; i < len; i++) arr[i] = val;
}
fill(nums, 5, 0);
/* Pointer arithmetic */
int *p = nums;
printf("%d\n", *(p + 2)); /* nums[2] */Comparing to JavaScript
Here's how you might have written similar code in JavaScript:
const nums = [1, 2, 3, 4, 5];
nums.push(6);
const len = nums.length;
// Slice
const sub = nums.slice(1, 4);
// Functional
const doubled = nums.map(n => n * 2);
// Pass by reference
function fill(arr, val) {
for (let i = 0; i < arr.length; i++) arr[i] = val;
}You may be used to different syntax or behavior.
C arrays are fixed-size; JS arrays are dynamic
You may be used to different syntax or behavior.
C dynamic arrays need malloc/realloc/free; JS uses push/pop
You may be used to different syntax or behavior.
C arrays decay to pointers when passed to functions
You may be used to different syntax or behavior.
C has no .length — pass size as a separate parameter
Step-by-Step Breakdown
1. Fixed vs Dynamic
C arrays are fixed at declaration. For dynamic size, use malloc and manage the memory yourself.
const arr = []; arr.push(1);int *arr = malloc(capacity * sizeof(int));
arr[0] = 1; /* manual index management */
free(arr); /* don't forget! */2. Arrays Become Pointers
When you pass a C array to a function, it 'decays' to a pointer. The length is lost — always pass it separately.
function fill(arr, val) { /* arr.length available */ }void fill(int *arr, int len, int val) {
for (int i = 0; i < len; i++) arr[i] = val;
}3. Pointer Arithmetic
C pointers can be incremented to traverse arrays. p+2 points to the third element. This is how C accesses array elements internally.
int arr[] = {10, 20, 30};
int *p = arr;
printf("%d\n", *(p+1)); /* 20 */Common Mistakes
When coming from JavaScript, developers often make these mistakes:
- C arrays are fixed-size; JS arrays are dynamic
- C dynamic arrays need malloc/realloc/free; JS uses push/pop
- C arrays decay to pointers when passed to functions
Key Takeaways
- Fixed arrays: int arr[N]; dynamic: malloc/free
- Arrays decay to pointers — pass length separately
- Pointer arithmetic traverses arrays
- Always check malloc return for NULL