Arrays
An array in C is a collection of elements of the same type, stored in contiguous memory locations. Arrays allow you to group related data together and access each element using an index.
Basic array declaration and usageβ
To declare an array, specify the data type of its elements followed by the array name and its size in square brackets:
int numbers[5]; // Declares an array of 5 integers
This creates space for 5 integers in memory, indexed from 0
to 4
. You can access and modify individual elements using their index:
numbers[0] = 10; // Assign 10 to the first element
numbers[1] = 20; // Assign 20 to the second element
int x = numbers[2]; // Retrieve value of third element
Array initializationβ
There are several ways to initialize arrays in C:
// Method 1: Initialize with values at declaration
int values[5] = {10, 20, 30, 40, 50};
// Method 2: Partial initialization (remaining elements are set to 0)
int partial[5] = {10, 20}; // Equivalent to {10, 20, 0, 0, 0}
// Method 3: Initialize all elements to zero
int zeros[100] = {0};
// Method 4: Let the compiler determine the size based on initializers
int auto_sized[] = {1, 2, 3, 4}; // Creates an array of size 4
Using {0}
initializes all elements to zero. This is a common technique for clearing arrays:
int arr[10] = {0}; // All 10 elements set to zero
int matrix[50][50] = {0}; // All 2500 elements set to zero
This works because C automatically sets any unspecified initializers to zero when you provide at least one initializer value.
Array input and outputβ
Reading array elements from inputβ
You can read array elements using scanf
:
int arr[5];
printf("Enter 5 integers: ");
for (int i = 0; i < 5; i++) {
scanf("%d", &arr[i]); // Note the & operator
}
Note that when you call scanf
, it requires the address of the variable where the input will be stored, not the value itself.
By using &arr[i]
, you pass the pointer to the iβth element of arr
. This ensures that each entered integer is written directly into the correct position in the array.
If you frequently need to print arrays, you can define a macro to simplify the process and avoid writing repetitive loops each time as follows:
#define PRINT_ARRAY(arr, size) \
for (int i = 0; i < (size); i++) \
printf("%d ", (arr)[i]);
// Usage
PRINT_ARRAY(a, SIZE);
Also, wrapping the macro body in a do { β¦ } while (0)
makes it behave like a single statement, preventing issues when used inside conditionals:
#define PRINT_ARRAY(arr, size) \
do { \
for (int i = 0; i < (size); i++) \
printf("%d ", (arr)[i]); \
} while (0)
// Safe in an if/else without braces
if (condition)
PRINT_ARRAY(a, SIZE);
else
printf("No array to print\n");
Reading array input with basic error handlingβ
When reading input into an array, it's good practice to check if the input is valid. Here is a way to do that:
#define SIZE 5
// and in main()...
int a[SIZE];
for (int i = 0; i < SIZE; i++) {
printf("Enter value %d: ", i);
// scanf needs the address of the variable to store the input
// The condition checks if scanf successfully read an integer
if (scanf("%d", &a[i]) != 1) {
printf("Invalid input\n");
break;
}
}
If the user enters something that is not an integer, the program prints an error message and stops reading further input. This helps prevent undefined behavior from invalid or unexpected input.
Notice that the scanf
function is called directly inside the if
condition:
if (scanf("%d", &a[i]) != 1) {
printf("Invalid input\n");
break;
}
This means scanf
is executed once, and its return value is immediately checked. There is no need to call scanf
again in an else
block, because the input has already been read (or attempted to be read) at this point.
Multidimensional arraysβ
C supports multidimensional arrays, which are essentially arrays of arrays:
// 2D array (3 rows, 4 columns)
int matrix[3][4] = {
{11, 12, 13, 14}, // Row 0
{21, 22, 23, 24}, // Row 1
{31, 32, 33, 34} // Row 2
};
// Access element at row 1, column 2
int value = matrix[1][2]; // Gets 23
Col 0 | Col 1 | Col 2 | Col 3 | |
---|---|---|---|---|
Row 0 | 11 | 12 | 13 | 14 |
Row 1 | 21 | 22 | 23 | 24 |
Row 2 | 31 | 32 | 33 | 34 |
You can create arrays with any number of dimensions:
// 3D array (2 matrices of 3Γ3)
int cube[2][3][3];
// Accessing elements
cube[0][1][2] = 99; // First matrix, second row, third column
To print them, use nested loops. For example, printing a 2D array is done like this:
#include <stdio.h>
int main() {
int matrix[3][4] = {
{11, 12, 13, 14},
{21, 22, 23, 24},
{31, 32, 33, 34}
};
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 4; j++) {
printf("%d ", matrix[i][j]);
}
printf("\n");
}
return 0;
}
11 12 13 14
21 22 23 24
31 32 33 34
You can extend this approach for higher-dimensional arrays by adding more nested loops.
Arrays and memoryβ
Arrays in C have a fixed size that must be known at compile time (for static arrays). The array name itself represents the memory address of the first element.
int nums[5] = {10, 20, 30, 40, 50};
printf("Address of first element: %p\n", nums); // Same as &nums[0]
The relationship between arrays and pointers is why array names can often be used interchangeably with pointers to their first element:
int *ptr = nums; // ptr points to nums[0]
printf("First element: %d\n", *ptr); // Prints 10
printf("Second element: %d\n", *(ptr + 1)); // Prints 20
This memory diagram might be helpful:
a
) acts as a pointer to the first element (p
is the same as a
here, they both point to the same location). Pointer arithmetic (such as p + 1
) moves to subsequent elements, just like incrementing the array index.Remember that each data type has a specific size; for example, an int
typically occupies 32 bits (4 bytes) in most C implementations.
Dynamic arraysβ
Static arrays have a fixed size determined at compile time. For variable-sized arrays allocated at runtime, C provides dynamic memory allocation:
```c
#include <stdio.h>
#include <stdlib.h>
int main() {
// Allocate an array of n integers
int size;
printf("Enter array size: ");
scanf("%d", &size);
int *dynamic_array = (int *)malloc(size * sizeof(int));
// Check if allocation was successful
if (dynamic_array == NULL) {
printf("Memory allocation failed\n");
return 1;
}
// Use the array
for (int i = 0; i < size; i++) {
dynamic_array[i] = i * 10;
}
// Print the array
printf("Array contents: ");
for (int i = 0; i < size; i++) {
printf("%d ", dynamic_array[i]);
}
printf("\n");
// Important: Free the memory when done
free(dynamic_array);
return 0;
}
Enter array size: 5
Array contents: 0 10 20 30 40
C99 introduced Variable-Length Arrays, which allow array sizes to be determined at runtime:
void process_data(int size) {
int variable_array[size]; // Size determined at runtime
// Use the array...
}
However, VLAs have limitations:
- They cannot be initialized at declaration
- They exist only until the end of their scope
- They can cause stack overflow with large sizes
- They're optional in C11 and later standards
For larger or longer-lived dynamic arrays, malloc()
is generally preferred.
Common pitfalls with arraysβ
- Bounds checking: C does not automatically check if an array index is valid. Accessing an element beyond the array bounds leads to undefined behavior.
int arr[3] = {1, 2, 3};
printf("%d\n", arr[5]); // Out-of-bounds access: undefined behavior
- Array size: Unlike some languages, C arrays do not track their own size. You must manage this information separately.
int arr[10];
// sizeof(arr) gives the total size in bytes
int size = sizeof(arr) / sizeof(arr[0]); // Calculates number of elements
printf("Array size: %d\n", size);
The strlen()
function is commonly used to determine the length of a string (a character array terminated by a null character '\0'
).
It cannot be used to find the size of a general array of numbers or other types.
For example:
char str[] = "hello";
printf("%zu\n", strlen(str)); // Prints 5 (number of characters before '\0')
But for non-string arrays (like int arr[10]
), strlen()
does not apply. Always use sizeof(arr) / sizeof(arr[0])
for such cases.
- Uninitialized arrays: elements of an array declared without initialization contain garbage values unless explicitly initialized.
int arr[5]; // Uninitialized array
for (int i = 0; i < 5; i++) {
printf("%d ", arr[i]); // Unpredictable output (garbage values)
}
- Array assignment: you cannot assign one array to another with the
=
operator. Instead, you must copy elements individually or use functions likememcpy()
.
int a[5] = {1, 2, 3, 4, 5};
int b[5];
// b = a; // Wrong! This does not work in C
// Correct way to copy:
for (int i = 0; i < 5; i++) {
b[i] = a[i];
}
Arrays are fundamental to C programming and serve as the foundation for many more complex data structures like strings, matrices, and tables.
π Exercise: Analyze weekly temperaturesβ
Let's try coding a C program that:
- Stores the temperatures for 7 days in an array.
- Calculates the average temperature.
- Prints the days (1-indexed) where the temperature was above average.
- Displays the average temperature and the number of days above average.
Solve this on your own before checking the solution!
Show solution
#include <stdio.h>
int main() {
// Declare and initialize an array
int temperatures[7] = {24, 22, 25, 23, 26, 25, 24};
// Calculate average temperature
int sum = 0;
for (int i = 0; i < 7; i++) {
sum += temperatures[i];
}
float average = (float)sum / 7;
// Find days above average
int above_average_count = 0;
printf("Days with above average temperature: ");
for (int i = 0; i < 7; i++) {
if (temperatures[i] > average) {
printf("%d ", i + 1); // Day number (1-indexed)
above_average_count++;
}
}
printf("\n");
printf("Average temperature: %.2fΒ°C\n", average);
printf("Number of days above average: %d\n", above_average_count);
return 0;
}
Days with above average temperature: 3 5 6
Average temperature: 24.14Β°C
Number of days above average: 3