Docs

Arrays

Arrays in C - One-Dimensional Arrays

Table of Contents

  1. •Introduction
  2. •What is an Array?
  3. •Array Declaration
  4. •Array Initialization
  5. •Accessing Array Elements
  6. •Array Memory Layout
  7. •Array Size and sizeof
  8. •Common Array Operations
  9. •Arrays and Loops
  10. •Array Bounds and Safety
  11. •Common Mistakes
  12. •Best Practices
  13. •Summary

Introduction

Arrays are one of the most fundamental and frequently used data structures in C programming. They allow you to store multiple values of the same type in contiguous memory locations, accessed using a single variable name and an index.


What is an Array?

An array is a collection of elements of the same data type stored in contiguous memory locations.

Key Characteristics

FeatureDescription
HomogeneousAll elements must be of the same type
ContiguousElements are stored in adjacent memory
Fixed SizeSize is determined at declaration
Zero-IndexedFirst element is at index 0
Random AccessAny element can be accessed directly

Visual Representation

Array: int numbers[5] = {10, 20, 30, 40, 50};

Index:    [0]    [1]    [2]    [3]    [4]
         ā”Œā”€ā”€ā”€ā”€ā”€ā”€ā”¬ā”€ā”€ā”€ā”€ā”€ā”€ā”¬ā”€ā”€ā”€ā”€ā”€ā”€ā”¬ā”€ā”€ā”€ā”€ā”€ā”€ā”¬ā”€ā”€ā”€ā”€ā”€ā”€ā”
Value:   │  10  │  20  │  30  │  40  │  50  │
         ā””ā”€ā”€ā”€ā”€ā”€ā”€ā”“ā”€ā”€ā”€ā”€ā”€ā”€ā”“ā”€ā”€ā”€ā”€ā”€ā”€ā”“ā”€ā”€ā”€ā”€ā”€ā”€ā”“ā”€ā”€ā”€ā”€ā”€ā”€ā”˜
Address: 1000   1004   1008   1012   1016
         (assuming 4 bytes per int)

Array Declaration

Syntax

data_type array_name[size];

Components

ComponentDescriptionExample
data_typeType of each elementint, float, char
array_nameIdentifier for the arraynumbers, grades
sizeNumber of elements5, 10, 100

Examples

int numbers[5];          // Array of 5 integers
float prices[10];        // Array of 10 floats
char letters[26];        // Array of 26 characters
double measurements[100]; // Array of 100 doubles

Size Must Be Known at Compile Time (C89)

// Valid (constant expression)
int arr1[5];
#define SIZE 10
int arr2[SIZE];
const int N = 5;
// int arr3[N];  // Not valid in C89, OK in C99+

// Invalid
int n = 5;
// int arr4[n];  // Not valid in C89 (Variable Length Array - C99+)

Array Initialization

Method 1: Initialize at Declaration

int numbers[5] = {10, 20, 30, 40, 50};

Method 2: Partial Initialization

int numbers[5] = {10, 20};  // Remaining elements are 0
// Result: {10, 20, 0, 0, 0}

Method 3: Initialize All to Zero

int numbers[5] = {0};       // All elements are 0
// Result: {0, 0, 0, 0, 0}

Method 4: Size from Initializer

int numbers[] = {10, 20, 30, 40, 50};  // Size is 5 (automatic)

Method 5: Designated Initializers (C99+)

int numbers[5] = {[0] = 10, [4] = 50};  // Specific indices
// Result: {10, 0, 0, 0, 50}

int arr[10] = {[3] = 30, [7] = 70};
// Result: {0, 0, 0, 30, 0, 0, 0, 70, 0, 0}

Method 6: Initialize After Declaration

int numbers[5];
numbers[0] = 10;
numbers[1] = 20;
numbers[2] = 30;
numbers[3] = 40;
numbers[4] = 50;

Initialization Comparison

ā”Œā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”
│                    ARRAY INITIALIZATION                        │
ā”œā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”¤
│                                                               │
│  int arr[5] = {1, 2, 3, 4, 5};    // All specified           │
│  Result: [1][2][3][4][5]                                      │
│                                                               │
│  int arr[5] = {1, 2};             // Partial                 │
│  Result: [1][2][0][0][0]                                      │
│                                                               │
│  int arr[5] = {0};                // All zeros               │
│  Result: [0][0][0][0][0]                                      │
│                                                               │
│  int arr[5];                      // Uninitialized (garbage) │
│  Result: [?][?][?][?][?]                                      │
│                                                               │
ā””ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”˜

Accessing Array Elements

Using Index Operator []

int numbers[5] = {10, 20, 30, 40, 50};

// Reading elements
int first = numbers[0];   // first = 10
int third = numbers[2];   // third = 30
int last = numbers[4];    // last = 50

// Writing elements
numbers[0] = 100;         // First element is now 100
numbers[4] = 500;         // Last element is now 500

Index Range

For an array of size N:

  • •Valid indices: 0 to N-1
  • •First element: array[0]
  • •Last element: array[N-1]
Array of size 5:
Valid indices: 0, 1, 2, 3, 4

           Index:  0    1    2    3    4
                 ā”Œā”€ā”€ā”€ā”€ā”¬ā”€ā”€ā”€ā”€ā”¬ā”€ā”€ā”€ā”€ā”¬ā”€ā”€ā”€ā”€ā”¬ā”€ā”€ā”€ā”€ā”
                 │    │    │    │    │    │
                 ā””ā”€ā”€ā”€ā”€ā”“ā”€ā”€ā”€ā”€ā”“ā”€ā”€ā”€ā”€ā”“ā”€ā”€ā”€ā”€ā”“ā”€ā”€ā”€ā”€ā”˜
                 First               Last

Array Memory Layout

Contiguous Memory

Arrays are stored in contiguous (adjacent) memory locations.

int arr[5] = {10, 20, 30, 40, 50};
Memory Address    Value
ā”Œā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”¬ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”
│    1000     │   10    │  arr[0]
ā”œā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”¼ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”¤
│    1004     │   20    │  arr[1]
ā”œā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”¼ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”¤
│    1008     │   30    │  arr[2]
ā”œā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”¼ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”¤
│    1012     │   40    │  arr[3]
ā”œā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”¼ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”¤
│    1016     │   50    │  arr[4]
ā””ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”“ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”˜

Address Calculation

The address of any element can be calculated:

Address of arr[i] = Base Address + (i Ɨ size of element)

For arr[3]:
Address = 1000 + (3 Ɨ 4) = 1000 + 12 = 1012

Relationship with Pointers

The array name is essentially a pointer to the first element:

int arr[5] = {10, 20, 30, 40, 50};

printf("%p\n", arr);      // Address of arr[0]
printf("%p\n", &arr[0]);  // Same address

// These are equivalent:
arr[i]   ↔   *(arr + i)

Array Size and sizeof

Calculating Array Size

int arr[5] = {10, 20, 30, 40, 50};

// Total size in bytes
size_t totalBytes = sizeof(arr);        // 20 bytes (5 Ɨ 4)

// Size of one element
size_t elementSize = sizeof(arr[0]);    // 4 bytes

// Number of elements
size_t numElements = sizeof(arr) / sizeof(arr[0]);  // 5

Important Notes

void printArray(int arr[]) {
    // sizeof(arr) here gives size of pointer, NOT array!
    // This is because arrays decay to pointers when passed to functions
}

// Solution: Pass size as parameter
void printArray(int arr[], int size) {
    for (int i = 0; i < size; i++) {
        printf("%d ", arr[i]);
    }
}

Common Array Operations

1. Finding Sum and Average

int arr[] = {10, 20, 30, 40, 50};
int size = 5;
int sum = 0;

for (int i = 0; i < size; i++) {
    sum += arr[i];
}

double average = (double)sum / size;

2. Finding Maximum and Minimum

int max = arr[0];
int min = arr[0];

for (int i = 1; i < size; i++) {
    if (arr[i] > max) max = arr[i];
    if (arr[i] < min) min = arr[i];
}

3. Searching for an Element

int target = 30;
int found = -1;

for (int i = 0; i < size; i++) {
    if (arr[i] == target) {
        found = i;
        break;
    }
}

4. Reversing an Array

for (int i = 0; i < size / 2; i++) {
    int temp = arr[i];
    arr[i] = arr[size - 1 - i];
    arr[size - 1 - i] = temp;
}

5. Copying an Array

int source[5] = {1, 2, 3, 4, 5};
int dest[5];

for (int i = 0; i < 5; i++) {
    dest[i] = source[i];
}

Arrays and Loops

For Loop (Most Common)

int arr[5] = {10, 20, 30, 40, 50};

// Forward traversal
for (int i = 0; i < 5; i++) {
    printf("%d ", arr[i]);
}

// Backward traversal
for (int i = 4; i >= 0; i--) {
    printf("%d ", arr[i]);
}

While Loop

int i = 0;
while (i < 5) {
    printf("%d ", arr[i]);
    i++;
}

Do-While Loop

int i = 0;
do {
    printf("%d ", arr[i]);
    i++;
} while (i < 5);

Array Bounds and Safety

Out-of-Bounds Access

C does not check array bounds. Accessing invalid indices causes undefined behavior.

int arr[5] = {10, 20, 30, 40, 50};

// DANGEROUS - Undefined Behavior!
arr[5] = 100;    // Writing beyond array
int x = arr[-1]; // Negative index
int y = arr[10]; // Far beyond array

Consequences of Out-of-Bounds

ā”Œā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”
│            OUT-OF-BOUNDS ACCESS CONSEQUENCES                │
ā”œā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”¤
│  • Reading garbage values                                   │
│  • Corrupting other variables                               │
│  • Causing segmentation faults (crash)                      │
│  • Security vulnerabilities (buffer overflow attacks)       │
│  • Unpredictable program behavior                           │
ā””ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”˜

Safe Programming Practices

#define SIZE 5
int arr[SIZE];

// Always check bounds
void safeAccess(int arr[], int size, int index) {
    if (index >= 0 && index < size) {
        printf("arr[%d] = %d\n", index, arr[index]);
    } else {
        printf("Error: Index %d out of bounds!\n", index);
    }
}

Common Mistakes

1. Off-by-One Errors

int arr[5];

// WRONG: Accesses arr[5] which doesn't exist
for (int i = 0; i <= 5; i++) {  // Should be i < 5
    arr[i] = i;
}

2. Uninitialized Arrays

int arr[5];  // Contains garbage values!

// WRONG: Using without initialization
int sum = 0;
for (int i = 0; i < 5; i++) {
    sum += arr[i];  // Adding garbage
}

3. Wrong Size Calculation

void function(int arr[]) {
    // WRONG: sizeof(arr) is size of pointer, not array
    int size = sizeof(arr) / sizeof(arr[0]);  // Incorrect!
}

4. Array Assignment

int arr1[5] = {1, 2, 3, 4, 5};
int arr2[5];

// WRONG: Cannot assign arrays directly
arr2 = arr1;  // Compilation error!

// CORRECT: Copy element by element
for (int i = 0; i < 5; i++) {
    arr2[i] = arr1[i];
}

5. Comparing Arrays

int arr1[5] = {1, 2, 3, 4, 5};
int arr2[5] = {1, 2, 3, 4, 5};

// WRONG: Compares addresses, not contents
if (arr1 == arr2) {  // Always false!
    printf("Equal\n");
}

// CORRECT: Compare element by element
int equal = 1;
for (int i = 0; i < 5; i++) {
    if (arr1[i] != arr2[i]) {
        equal = 0;
        break;
    }
}

Best Practices

1. Use Named Constants for Size

#define MAX_STUDENTS 100
int grades[MAX_STUDENTS];

// Or using const (C99+)
const int SIZE = 100;

2. Always Initialize Arrays

int arr[5] = {0};  // Initialize all to zero

3. Use sizeof Pattern for Length

int arr[] = {1, 2, 3, 4, 5};
int length = sizeof(arr) / sizeof(arr[0]);

4. Pass Size with Array to Functions

void processArray(int arr[], int size) {
    for (int i = 0; i < size; i++) {
        // Process arr[i]
    }
}

5. Check Bounds Before Access

if (index >= 0 && index < size) {
    arr[index] = value;
}

Summary

Quick Reference

ConceptSyntax/Example
Declarationint arr[5];
Initializationint arr[5] = {1, 2, 3, 4, 5};
Accessarr[0], arr[4]
First elementarr[0]
Last elementarr[size-1]
Size in bytessizeof(arr)
Number of elementssizeof(arr)/sizeof(arr[0])

Key Points to Remember

āœ“ Arrays are zero-indexed (first index is 0)
āœ“ Size must be known at compile time (C89)
āœ“ Elements are stored contiguously in memory
āœ“ No bounds checking in C - be careful!
āœ“ Array name acts as pointer to first element
āœ“ Cannot assign or compare arrays directly
āœ“ Always pass size when passing array to function

Array Memory Model

Declaration: int arr[5];

Stack Memory:
ā”Œā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”
│                                             │
│   arr[0] │ arr[1] │ arr[2] │ arr[3] │ arr[4]│
│    4B    │   4B   │   4B   │   4B   │   4B  │
│                                             │
│   ← ─ ─ ─ ─ ─ Total: 20 bytes ─ ─ ─ ─ ─ →  │
ā””ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”˜

Next Steps

After mastering one-dimensional arrays:

  1. •Learn about Multi-dimensional Arrays
  2. •Understand Arrays and Pointers relationship
  3. •Study Passing Arrays to Functions
  4. •Explore Dynamic Arrays with malloc

"Arrays are the simplest yet most powerful data structure - master them well."

Arrays - C Programming Tutorial | DeepML