Docs
Arrays
Arrays in C - One-Dimensional Arrays
Table of Contents
- ā¢Introduction
- ā¢What is an Array?
- ā¢Array Declaration
- ā¢Array Initialization
- ā¢Accessing Array Elements
- ā¢Array Memory Layout
- ā¢Array Size and sizeof
- ā¢Common Array Operations
- ā¢Arrays and Loops
- ā¢Array Bounds and Safety
- ā¢Common Mistakes
- ā¢Best Practices
- ā¢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
| Feature | Description |
|---|---|
| Homogeneous | All elements must be of the same type |
| Contiguous | Elements are stored in adjacent memory |
| Fixed Size | Size is determined at declaration |
| Zero-Indexed | First element is at index 0 |
| Random Access | Any 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
| Component | Description | Example |
|---|---|---|
| data_type | Type of each element | int, float, char |
| array_name | Identifier for the array | numbers, grades |
| size | Number of elements | 5, 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
| Concept | Syntax/Example |
|---|---|
| Declaration | int arr[5]; |
| Initialization | int arr[5] = {1, 2, 3, 4, 5}; |
| Access | arr[0], arr[4] |
| First element | arr[0] |
| Last element | arr[size-1] |
| Size in bytes | sizeof(arr) |
| Number of elements | sizeof(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:
- ā¢Learn about Multi-dimensional Arrays
- ā¢Understand Arrays and Pointers relationship
- ā¢Study Passing Arrays to Functions
- ā¢Explore Dynamic Arrays with malloc
"Arrays are the simplest yet most powerful data structure - master them well."