Arrays
Imagine a row of lockers, each numbered starting from 0, storing items of the same kind -- that is an array. It lets you manage a group of same-type data under one name.
Defining and Initializing One-Dimensional Arrays
An array is an ordered collection of elements of the same type, stored contiguously in memory. When defining an array, you specify the element type and the number of elements.
int scores[5];
This defines an array of 5 int elements, but the contents are uninitialized and the values are indeterminate. It is recommended to initialize the array at definition:
int scores[5] = {90, 85, 78, 92, 88};
If the initializer list is shorter than the array, the remaining elements are automatically set to 0:
int data[5] = {10, 20};
Now data[2], data[3], and data[4] are all 0. Using this property, you can zero out an entire array:
int zeros[100] = {0};
If you provide a complete initializer list, you can omit the array length and the compiler will calculate it automatically:
int days[] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
Subscript Access
Array elements are accessed by subscript (index), starting from 0. For an array of length N, the valid subscripts range from 0 to N-1.
int scores[5] = {90, 85, 78, 92, 88};
int first = scores[0];
int last = scores[4];
scores[2] = 100;
The subscript can be an integer expression, which makes loop traversal convenient:
int i = 3;
int val = scores[i];
Out-of-Bounds Risks
C does not check whether array subscripts are out of bounds. Accessing out-of-bounds elements is undefined behavior -- it may read garbage data, modify other variables, or crash the program.
int arr[3] = {10, 20, 30};
printf("%d\n", arr[3]);
printf("%d\n", arr[-1]);
Both lines access illegal positions. The compiler will not warn you, but the results are unpredictable.
< rather than <= when comparing against the length.
Array Traversal
Using a for loop to process each element sequentially is the most common array operation:
int scores[5] = {90, 85, 78, 92, 88};
int i;
for (i = 0; i < 5; i++) {
printf("scores[%d] = %d\n", i, scores[i]);
}
Sum all elements:
int sum = 0;
for (i = 0; i < 5; i++) {
sum += scores[i];
}
printf("Total: %d\n", sum);
Find the maximum value:
int max = scores[0];
for (i = 1; i < 5; i++) {
if (scores[i] > max) {
max = scores[i];
}
}
printf("Highest: %d\n", max);
Example
Calculate the average score and the number of failing grades:
#include <stdio.h>
int main(void) {
double scores[] = {78.5, 92.0, 55.5, 88.0, 43.0, 67.5, 90.0};
int len = sizeof(scores) / sizeof(scores[0]);
double sum = 0;
int fail = 0;
int i;
for (i = 0; i < len; i++) {
sum += scores[i];
if (scores[i] < 60.0) {
fail++;
}
}
printf("Average: %.1f\n", sum / len);
printf("Failing: %d\n", fail);
return 0;
}
Average: 73.5
Failing: 2
Here, sizeof(scores) / sizeof(scores[0]) dynamically calculates the number of elements, so you do not need to update the loop condition when changing the array contents.
Arrays as Function Parameters
When an array is passed to a function, the entire array is not copied -- only the address of the first element is passed. This means the function cannot determine the array length using sizeof; the length must be passed as a separate parameter.
void print_array(int arr[], int len) {
int i;
for (i = 0; i < len; i++) {
printf("%d ", arr[i]);
}
printf("\n");
}
The parameter int arr[] is equivalent to int *arr, which reflects the "decay" to a pointer. Modifying array elements inside the function affects the original array because both operate on the same memory.
void double_values(int arr[], int len) {
int i;
for (i = 0; i < len; i++) {
arr[i] *= 2;
}
}
int main(void) {
int data[] = {1, 2, 3, 4, 5};
double_values(data, 5);
return 0;
}
After the call, data contains {2, 4, 6, 8, 10}.
Two-Dimensional Arrays
A two-dimensional array can be thought of as an "array of arrays", commonly used to represent matrices or tabular data.
int matrix[3][4];
This defines a 3-row, 4-column two-dimensional array. Initialization can be grouped by row:
int matrix[3][4] = {
{1, 2, 3, 4},
{5, 6, 7, 8},
{9, 10, 11, 12}
};
It can also be written flat -- the effect is the same:
int matrix[3][4] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12};
Access elements using two subscripts:
int val = matrix[1][2];
matrix[0][0] = 100;
Traversing a two-dimensional array requires a double loop:
int i, j;
for (i = 0; i < 3; i++) {
for (j = 0; j < 4; j++) {
printf("%4d", matrix[i][j]);
}
printf("\n");
}
When initializing, you can omit the row count but not the column count:
int m[][4] = {
{1, 2, 3, 4},
{5, 6, 7, 8}
};
The compiler infers 2 rows from the initializer data.
Example
Calculate the average score across 4 subjects for 3 students:
#include <stdio.h>
void student_avg(double grades[][4], int rows) {
int i, j;
for (i = 0; i < rows; i++) {
double sum = 0;
for (j = 0; j < 4; j++) {
sum += grades[i][j];
}
printf("Student%d Average: %.1f\n", i + 1, sum / 4);
}
}
int main(void) {
double grades[3][4] = {
{85.0, 90.0, 78.0, 92.0},
{70.0, 65.0, 80.0, 75.0},
{95.0, 88.0, 92.0, 97.0}
};
student_avg(grades, 3);
return 0;
}
Student1 Average: 86.2
Student2 Average: 72.5
Student3 Average: 93.0
❓ FAQ
sizeof(arr) be used inside a function to find the element count?sizeof gives the pointer size (4 or 8 bytes), not the total array size.📖 Summary
- Arrays are contiguous storage of same-type elements, with subscripts starting from 0
- The length can be omitted during initialization; partial initialization fills remaining elements with 0
- C does not perform bounds checking -- the programmer must ensure subscripts are valid
- Arrays decay to pointers when passed to functions; the length must be passed separately
- Two-dimensional arrays are stored row by row; the column count must be specified in function parameters
📝 Exercises
- Write a program that reads 10 integers into an array, then prints all elements in reverse order.
- Write a function that receives an integer array and its length, and returns the index of the maximum value.
- Define a 4x4 integer matrix, initialize it, and calculate the sum of both diagonals.



