0% found this document useful (0 votes)
4 views19 pages

Arrays in C

The document provides a comprehensive guide on arrays in C programming, covering topics such as declaration, initialization, traversal, and multi-dimensional arrays. It explains key characteristics of arrays, their memory layout, and common operations, while also addressing the relationship between arrays and pointers. Additionally, it discusses passing arrays to functions and the implications of array decay to pointers.
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
4 views19 pages

Arrays in C

The document provides a comprehensive guide on arrays in C programming, covering topics such as declaration, initialization, traversal, and multi-dimensional arrays. It explains key characteristics of arrays, their memory layout, and common operations, while also addressing the relationship between arrays and pointers. Additionally, it discusses passing arrays to functions and the implications of array decay to pointers.
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd

Arrays in C

A Complete 8-Chapter Reference


Declaration · Traversal · Pointers · Dynamic Allocation

C Programming Language Series


C Programming Language Arrays — A Complete Guide

Chapter 1

Introduction to Arrays

1.1 What is an Array?


An array in C is a contiguous collection of elements of the same data type, stored sequentially in memory
under a single variable name. Each element in the array can be accessed individually using an index or
subscript.

Instead of declaring multiple variables like score1, score2, …, score100, you declare one array: int
scores[100];. This single declaration reserves memory for 100 integers, all adjacent to each other in
memory.

Analogy: Think of an array as a row of mailboxes. The entire row has one name (e.g.,
"Mailboxes"). Each individual mailbox has a number (0, 1, 2, …) and can hold one item. All
mailboxes are the same size and are placed side by side.

1.2 Key Characteristics of Arrays in C


1. Homogeneous Elements: All elements must be of the same data type (int, char, float,
struct, etc.).
2. Contiguous Memory: Elements are stored in consecutive memory locations, allowing pointer
arithmetic to work seamlessly with arrays.
3. Fixed Size: The size must be known at compile time (unless using C99 VLAs). Once declared, the
size cannot change.
4. Zero-Based Indexing: The first element is at index 0, the last at index size - 1.
5. Random Access: Any element can be accessed directly in O(1) time using its index.
6. No Bounds Checking: C does not check if an index is within bounds. Accessing beyond the array
leads to undefined behavior.

1.3 Why Use Arrays?


• Organization: Group related data under one name.
• Efficiency: Process many elements with loops instead of repetitive code.
• Memory Locality: Contiguous storage improves cache performance.
• Foundation for Data Structures: Arrays form the basis for strings, matrices, dynamic arrays, and
more complex structures.

1.4 Visualizing Array Memory


Consider the declaration: int arr[5] = {10, 20, 30, 40, 50}; Assuming an int occupies 4
bytes and the array starts at address 1000:

Element Index Address Value

arr[0] 0 1000 10

—2—
C Programming Language Arrays — A Complete Guide

arr[1] 1 1004 20

arr[2] 2 1008 30

arr[3] 3 1012 40

arr[4] 4 1016 50

The address of arr[i] = base address + (i × size of each element).

—3—
C Programming Language Arrays — A Complete Guide

Chapter 2

Declaration, Initialization, and Access

2.1 Declaring an Array


Syntax:
data_type array_name[array_size];

• data_type: Any valid C type.


• array_name: A valid C identifier.
• array_size: A positive integer constant expression known at compile time.

Array declaration examples


int numbers[10]; // Array of 10 integers
char name[50]; // Array of 50 characters (49-char string + '\0')
float temperatures[31]; // Array of 31 floats
double matrix[100]; // Array of 100 doubles

2.2 Initializing Arrays


All initialization methods
// Method 1: Initialization at declaration
int arr[5] = {1, 2, 3, 4, 5}; // All 5 elements initialized
int arr2[5] = {1, 2}; // First two: 1,2; remaining: 0
int arr3[] = {1, 2, 3, 4, 5}; // Size deduced as 5

// Method 2: Partial initialization


int arr4[10] = {0}; // All 10 elements set to 0
int arr5[10] = {5}; // First element 5, rest 0

// Method 3: Designated initializers (C99)


int arr6[5] = {[2] = 10, [4] = 20}; // arr[2]=10, arr[4]=20, others 0

// Method 4: Character array (strings)


char str1[] = "Hello"; // Size 6 (includes '\0')
char str2[] = {'H','e','l','l','o','\0'}; // Same as above
char str3[10] = "Hello"; // First 5 chars, rest '\0'

2.3 Accessing Array Elements


Use the subscript operator [] with an index. Indices range from 0 to size - 1.

—4—
C Programming Language Arrays — A Complete Guide

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

printf("%d\n", arr[0]); // Output: 10


printf("%d\n", arr[2]); // Output: 30
printf("%d\n", arr[4]); // Output: 50

arr[1] = 99; // Modify second element


printf("%d\n", arr[1]); // Output: 99

2.4 Common Pitfall: Out-of-Bounds Access


C does not prevent accessing indices beyond the array bounds. This leads to undefined behavior — the
program might crash, produce garbage output, or silently corrupt data.

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


arr[5] = 100; // ERROR: index 5 is out of bounds (valid: 0-4)
arr[-1] = 10; // ERROR: negative index

2.5 The sizeof Operator with Arrays


int arr[20];
size_t total_bytes = sizeof(arr); // 80 (if int = 4 bytes)
size_t element_bytes = sizeof(arr[0]); // 4
size_t length = sizeof(arr) / sizeof(arr[0]); // 20

Important: sizeof only works on the actual array variable, not on a pointer to it. When an array is passed to a
function it 'decays' to a pointer — sizeof will then return the pointer size (usually 8 bytes), not the array size.

—5—
C Programming Language Arrays — A Complete Guide

Chapter 3

Traversing and Processing Arrays

3.1 Basic Traversal with a for Loop


Read, store, and print an array
#include <stdio.h>
#define SIZE 5

int main() {
int arr[SIZE];

// Input
printf("Enter %d integers: ", SIZE);
for (int i = 0; i < SIZE; i++) {
scanf("%d", &arr[i]);
}

// Output
printf("You entered: ");
for (int i = 0; i < SIZE; i++) {
printf("%d ", arr[i]);
}
printf("\n");
return 0;
}

3.2 Common Array Operations


Common array operations

—6—
C Programming Language Arrays — A Complete Guide

// Sum of elements
int sum = 0;
for (int i = 0; i < SIZE; i++) sum += arr[i];

// Find maximum element


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

// Reverse an array in-place


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

// Linear search
int search(int arr[], int size, int target) {
for (int i = 0; i < size; i++) {
if (arr[i] == target) return i; // Found
}
return -1; // Not found
}

3.3 Using while and do-while Loops


int i = 0;

// while loop traversal


while (i < SIZE) {
printf("%d ", arr[i]);
i++;
}

// do-while (at least one iteration)


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

3.4 Multi-pass Processing — Bubble Sort


Bubble sort — multi-pass algorithm

—7—
C Programming Language Arrays — A Complete Guide

void bubbleSort(int arr[], int size) {


for (int i = 0; i < size - 1; i++) {
for (int j = 0; j < size - i - 1; j++) {
if (arr[j] > arr[j + 1]) {
int temp = arr[j];
arr[j] = arr[j + 1];
arr[j + 1] = temp;
}
}
}
}

—8—
C Programming Language Arrays — A Complete Guide

Chapter 4

Multi-Dimensional Arrays

4.1 Declaring and Initializing 2D Arrays


A two-dimensional array is essentially an array of arrays, often visualised as a matrix with rows and
columns.

Declaration syntax: data_type array_name[rows][columns];

2D array initialization methods


// Method 1: Nested braces (recommended)
int matrix[2][3] = {
{1, 2, 3},
{4, 5, 6}
};

// Method 2: Flat list (row-major order)


int matrix2[2][3] = {1, 2, 3, 4, 5, 6};

// Method 3: Partial initialization (remaining set to 0)


int matrix3[2][3] = {{1, 2}, {4}}; // Row0: 1,2,0; Row1: 4,0,0

// Method 4: Omit first dimension


int matrix4[][3] = {{1,2,3},{4,5,6}}; // Compiler infers rows = 2

4.2 Accessing 2D Array Elements


int matrix[2][3] = {{1,2,3},{4,5,6}};

printf("%d\n", matrix[0][1]); // Output: 2


printf("%d\n", matrix[1][2]); // Output: 6

matrix[1][1] = 99; // Change element at row1,col1

4.3 Memory Layout — Row-Major Order


C stores 2D arrays in row-major order: all elements of row 0 come first, then row 1, etc. For int
arr[2][3] = {{1,2,3},{4,5,6}};:

Address Value Element

1000 1 arr[0][0]

1004 2 arr[0][1]

1008 3 arr[0][2]

—9—
C Programming Language Arrays — A Complete Guide

1012 4 arr[1][0]

1016 5 arr[1][1]

1020 6 arr[1][2]

4.4 Traversing 2D Arrays


// Nested loops
for (int i = 0; i < rows; i++) {
for (int j = 0; j < cols; j++) {
printf("%d ", matrix[i][j]);
}
printf("\n");
}

// Row-major traversal with a single pointer (advanced)


int *p = &matrix[0][0];
for (int i = 0; i < rows * cols; i++) {
printf("%d ", p[i]);
}

4.5 3D and Higher-Dimensional Arrays


int tensor[3][4][5]; // 3 layers, 4 rows, 5 cols (60 elements)

int tensor2[2][2][2] = {
{{1,2},{3,4}},
{{5,6},{7,8}}
};

printf("%d\n", tensor2[1][0][1]); // Output: 6

— 10 —
C Programming Language Arrays — A Complete Guide

Chapter 5

Arrays and Functions

5.1 Passing Arrays to Functions


When you pass an array to a function, what is actually passed is a pointer to the first element. The array
"decays" to a pointer. The function receives the address, not a copy of the entire array.

• The function can modify the original array (no copy is made).
• The size information is lost; you must pass the size separately.
All three prototypes below are equivalent: void process(int arr[], int size); / void process(int *arr, int size); / void
process(int arr[10], int size); — the 10 is ignored by the compiler.

Array passed to function — original is modified


void doubleElements(int arr[], int size) {
for (int i = 0; i < size; i++) {
arr[i] *= 2; // Modifies original array
}
}

int main() {
int numbers[] = {1, 2, 3, 4, 5};
int size = sizeof(numbers) / sizeof(numbers[0]);

doubleElements(numbers, size);

for (int i = 0; i < size; i++) {


printf("%d ", numbers[i]); // Output: 2 4 6 8 10
}
return 0;
}

5.2 Passing Multi-Dimensional Arrays


For 2D arrays, you must specify the number of columns. The first dimension can be omitted.

— 11 —
C Programming Language Arrays — A Complete Guide

// C99: variable-length array in parameter


void printMatrix(int rows, int cols, int matrix[][cols]) {
for (int i = 0; i < rows; i++) {
for (int j = 0; j < cols; j++) {
printf("%d ", matrix[i][j]);
}
printf("\n");
}
}

// Fixed column count


void printMatrixFixed(int matrix[][4], int rows) {
for (int i = 0; i < rows; i++) {
for (int j = 0; j < 4; j++) {
printf("%d ", matrix[i][j]);
}
printf("\n");
}
}

5.3 Returning Arrays from Functions


You cannot return a local array from a function — it goes out of scope. Instead, use one of these
approaches:

1. Modify an array passed as a parameter (most common).


2. Return a pointer to dynamically allocated memory (using malloc).
3. Wrap the array in a struct (copyable, but inefficient for large arrays).

Return dynamically allocated array


int* createArray(int size) {
int *arr = (int*)malloc(size * sizeof(int));
if (arr != NULL) {
for (int i = 0; i < size; i++) arr[i] = 0;
}
return arr; // Caller must free()
}

5.4 Array of Function Pointers (Advanced)


Array of function pointers — dispatch table

— 12 —
C Programming Language Arrays — A Complete Guide

int add(int a, int b) { return a + b; }


int sub(int a, int b) { return a - b; }
int mul(int a, int b) { return a * b; }

int main() {
int (*operations[3])(int, int) = {add, sub, mul};

for (int i = 0; i < 3; i++) {


printf("%d\n", operations[i](10, 5)); // 15, 5, 50
}
return 0;
}

— 13 —
C Programming Language Arrays — A Complete Guide

Chapter 6

Arrays and Pointers Relationship

6.1 Array Name as a Constant Pointer


The name of an array is a constant pointer to its first element. arr is equivalent to &arr[0].

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


int *ptr = arr; // ptr points to arr[0]

printf("%d\n", *arr); // Output: 10


printf("%d\n", *(arr+2)); // Output: 30

6.2 Pointer Arithmetic with Arrays


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

printf("%d\n", *ptr); // 10
ptr++; // Move to next element
printf("%d\n", *ptr); // 20
ptr += 2; // Move two more elements
printf("%d\n", *ptr); // 40

6.3 Subscript vs. Pointer Notation


The expression arr[i] is exactly equivalent to *(arr + i). The compiler converts subscript notation
to pointer arithmetic internally.

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


int i = 2;

printf("%d\n", arr[i]); // 3
printf("%d\n", *(arr + i)); // 3
printf("%d\n", i[arr]); // 3 — valid but never use this!

6.4 Differences Between Arrays and Pointers


Aspect Array Pointer

Storage Allocates memory for elements Stores an address only

sizeof Returns total bytes of all elements Returns address size (usually 8 bytes)

Assignment Cannot reassign the array name Can point to different addresses

Function decay Decays to pointer when passed Remains a pointer

— 14 —
C Programming Language Arrays — A Complete Guide

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


int *ptr = arr;

printf("%zu\n", sizeof(arr)); // 20 (if int = 4 bytes)


printf("%zu\n", sizeof(ptr)); // 8 (on 64-bit system)

// arr = ptr; // ERROR: cannot assign to array name


ptr = arr + 2; // OK: pointer can be reassigned

6.5 Array of Pointers


String array — array of char pointers
const char *fruits[3] = {"Apple", "Banana", "Cherry"};

for (int i = 0; i < 3; i++) {


printf("%s\n", fruits[i]); // Each fruits[i] is a char*
}

— 15 —
C Programming Language Arrays — A Complete Guide

Chapter 7

VLAs, Dynamic Arrays & Flexible Members

7.1 Variable-Length Arrays (C99)


C99 introduced Variable-Length Arrays (VLAs), where the array size can be determined at runtime using
a variable.

int n;
printf("Enter size: ");
scanf("%d", &n);
int arr[n]; // VLA: size determined at runtime

for (int i = 0; i < n; i++) arr[i] = i;

Important VLA limitations:

• Not supported in C++ or pre-C99 standards.


• Cannot have global scope or static/extern storage class.
• Cannot be partially initialized (e.g., int arr[n] = {0} is not allowed).
• Large VLAs on the stack can cause stack overflow.

7.2 Dynamic Arrays (Heap Allocation)


For full runtime flexibility without VLA limitations, use dynamic memory allocation with pointers.

Dynamic array with realloc resizing


int n;
scanf("%d", &n);

int *arr = (int*)malloc(n * sizeof(int));


if (arr == NULL) { printf("Allocation failed\n"); return 1; }

for (int i = 0; i < n; i++) arr[i] = i;

// Resize using realloc


int new_n = n * 2;
int *temp = (int*)realloc(arr, new_n * sizeof(int));
if (temp != NULL) {
arr = temp;
for (int i = n; i < new_n; i++) arr[i] = 0;
}

free(arr);
arr = NULL;

— 16 —
C Programming Language Arrays — A Complete Guide

7.3 Dynamic 2D Arrays


Jagged 2D array
// Method 1: Array of pointers (jagged array)
int rows = 3, cols = 4;
int **matrix = (int**)malloc(rows * sizeof(int*));
for (int i = 0; i < rows; i++)
matrix[i] = (int*)malloc(cols * sizeof(int));

// Access: matrix[row][col]

// Freeing:
for (int i = 0; i < rows; i++) free(matrix[i]);
free(matrix);

Flat 2D array — better cache performance


// Method 2: Single contiguous block (better cache locality)
int *matrix = (int*)malloc(rows * cols * sizeof(int));

// Access: matrix[row * cols + col]


matrix[1 * cols + 2] = 42; // Row 1, Col 2

free(matrix);

7.4 Flexible Array Members (C99)


A structure can have an array of unspecified size as its last member, useful for creating variable-sized
objects allocated in one block.

Flexible array member in a struct


typedef struct {
int length;
int data[]; // Flexible array member — must be last
} FlexArray;

// Allocation
FlexArray *arr = (FlexArray*)malloc(sizeof(FlexArray) + 10 * sizeof(int));
arr->length = 10;
for (int i = 0; i < arr->length; i++) arr->data[i] = i;

free(arr);

— 17 —
C Programming Language Arrays — A Complete Guide

Chapter 8

Pitfalls, Best Practices & Advanced Examples

8.1 Common Pitfalls with Arrays


Pitfall Example Consequence

Off-by-one errors for(i=0; i<=SIZE; i++) Access beyond bounds

Missing null terminator char str[3] = "abc"; No space for '\0'

sizeof on pointer param void f(int a[]) { sizeof(a); } Returns pointer size, not array size

Returning local array int* f() { int a[5]; return a; } Dangling pointer — undefined behavior

Uninitialized elements int arr[5]; printf("%d", arr[0]); Garbage value printed

Unsafe strcpy strcpy(dest, src) where src is too long Buffer overflow

8.2 Best Practices Summary


1. Always know your array bounds and enforce them in every loop.
2. Use const for read-only parameters: void print(const int arr[], int size).
3. Pass size explicitly when passing arrays to functions.
4. Initialize arrays to avoid garbage values: int arr[100] = {0};
5. Use sizeof(arr)/sizeof(arr[0]) for compile-time size calculation.
6. For strings, leave room for '\0' and prefer strncpy, snprintf.
7. Free dynamically allocated memory and set pointers to NULL.
8. Use assert to validate indices in debug builds.
9. Prefer single contiguous blocks for 2D arrays when cache performance matters.
10. Consider flexible array members for variable-sized structures.

8.3 Advanced Example — Generic Linear Search


Generic linear search — void* and function pointers

— 18 —
C Programming Language Arrays — A Complete Guide

#include <stdio.h>
#include <stdlib.h>

// Generic linear search using void* and function pointer


void* linearSearch(void *base, size_t nmemb, size_t size,
const void *key,
int (*compare)(const void*, const void*)) {
char *ptr = (char*)base;
for (size_t i = 0; i < nmemb; i++) {
if (compare(ptr + i * size, key) == 0) {
return ptr + i * size;
}
}
return NULL;
}

int compareInt(const void *a, const void *b) {


return *(int*)a - *(int*)b;
}

int main() {
int arr[] = {10, 20, 30, 40, 50};
int key = 30;
int *result = (int*)linearSearch(arr, 5, sizeof(int), &key, compareInt);

if (result) {
printf("Found: %d at index %ld\n", *result, result - arr);
}
return 0;
}

8.4 Conclusion
Arrays are fundamental to C programming, providing a powerful way to manage collections of data.
Understanding the relationship between arrays and pointers, memory layout, and the limitations of static
arrays is essential for every C programmer.

While static arrays are simple and efficient for fixed-size data, dynamic allocation offers flexibility at the
cost of manual memory management. Mastery of arrays enables you to implement complex data
structures, process large datasets efficiently, and write systems-level code.

Always practice safe array handling: respect bounds, initialize properly, and pass sizes explicitly to
functions.

End of Document — Arrays in C: A Complete Guide

— 19 —

You might also like