How to Sort an Array in C
Sorting an array in C is one of those tasks that looks simple on the surface and then turns into a small decision tree once you start writing real code. Do you need ascending order or descending order? Are you sorting integers, floats, or strings? Is the array tiny, or is it large enough that algorithm choice matters? Do you need the original data preserved, or is it fine to rearrange the values in place?
The short version is this: C does not give you a built-in sort() for normal arrays. You either implement the sorting logic yourself or use qsort() from the standard library. For most practical cases, qsort() is the fastest way to get correct code with minimal effort. If you are learning, though, writing a simple bubble sort or selection sort is still useful because it teaches how comparisons and swaps work at the memory level.
The basic idea
An array is just a contiguous block of memory. Sorting means reordering the values so that they follow a rule, usually smallest to largest. Because C exposes the raw array directly, the sort algorithm has to work by comparing elements and swapping them in place.
A comparison-based sort asks a simple question repeatedly:
- Is element A greater than element B?
- If yes, should they be swapped?
- If no, should we leave them alone?
That repeated comparison is the entire core of most basic sorting routines.
A quick comparison of common approaches
| Method | Best for | Time complexity | Notes |
|---|---|---|---|
| Bubble sort | Learning basics | O(n^2) | Easy to understand, slow on large arrays |
| Selection sort | Learning swaps | O(n^2) | Fewer swaps than bubble sort |
| Insertion sort | Small or nearly sorted arrays | O(n^2) | Often good for tiny datasets |
qsort() | General use | Usually O(n log n) average | Standard library solution |
If you are writing production code, the standard library option is usually the right answer. If you are solving a homework exercise or want to understand the mechanics, start with a simple manual algorithm.
Sorting with bubble sort
Bubble sort is the classic beginner algorithm. It repeatedly walks through the array and swaps adjacent elements if they are out of order. After each full pass, the largest remaining value “bubbles” toward the end.
Here is a straightforward ascending-order version for integers:
void bubble_sort(int arr[], int n) {
for (int i = 0; i < n - 1; i++) {
for (int j = 0; j < n - 1 - i; j++) {
if (arr[j] > arr[j + 1]) {
int temp = arr[j];
arr[j] = arr[j + 1];
arr[j + 1] = temp;
}
}
}
}
int main(void) {
int arr[] = {64, 25, 12, 22, 11};
int n = sizeof(arr) / sizeof(arr[0]);
bubble_sort(arr, n);
for (int i = 0; i < n; i++) {
printf("%d ", arr[i]);
}
printf("\n");
return 0;
}
Why this works
The inner loop compares neighboring values and swaps them when they are in the wrong order. The outer loop repeats that process enough times to guarantee that every element reaches the correct place.
What to notice
n - 1 - ishortens the inner loop after each pass because the right side is already sorted.- The array is modified in place.
- The function works only for
intvalues as written, but the pattern is reusable.
Sorting with selection sort
Selection sort improves the idea slightly by reducing the number of swaps. Instead of swapping every time it sees a bad pair, it scans the rest of the array to find the smallest value and places it in the current position.
#include <stdio.h>
void selection_sort(int arr[], int n) {
for (int i = 0; i < n - 1; i++) {
int min_index = i;
for (int j = i + 1; j < n; j++) {
if (arr[j] < arr[min_index]) {
min_index = j;
}
}
if (min_index != i) {
int temp = arr[i];
arr[i] = arr[min_index];
arr[min_index] = temp;
}
}
}
Selection sort is still quadratic, so it is not a great choice for huge data. But it is simple, predictable, and easy to trace in a debugger.
Sorting with qsort()
For real code, qsort() is the standard C library function most people should reach for first. It lives in <stdlib.h> and can sort arrays of many types as long as you provide a comparison function.
#include <stdio.h>
#include <stdlib.h>
int compare_ints(const void *a, const void *b) {
int int_a = *(const int *)a;
int int_b = *(const int *)b;
if (int_a < int_b) return -1;
if (int_a > int_b) return 1;
return 0;
}
int main(void) {
int arr[] = {64, 25, 12, 22, 11};
int n = sizeof(arr) / sizeof(arr[0]);
qsort(arr, n, sizeof(int), compare_ints);
for (int i = 0; i < n; i++) {
printf("%d ", arr[i]);
}
printf("\n");
return 0;
}
How qsort() works
The function signature looks strange at first because C is working through generic pointers:
arris the base address of the array.nis the number of elements.sizeof(int)tellsqsort()how many bytes each element occupies.compare_intsdecides ordering.
That comparison function is the important piece. It must return:
- a negative value if the first element should come before the second,
- zero if they are equal,
- a positive value if the first should come after the second.
Descending order
If you want descending order, you can reverse the comparison logic.
int compare_ints_desc(const void *a, const void *b) {
int int_a = *(const int *)a;
int int_b = *(const int *)b;
if (int_a > int_b) return -1;
if (int_a < int_b) return 1;
return 0;
}
That is usually cleaner than sorting ascending and then reversing the array afterward.
Sorting strings
Sorting strings in C is a separate case because strings are arrays of characters, and arrays of strings are usually represented as an array of pointers.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int compare_strings(const void *a, const void *b) {
const char *const *sa = a;
const char *const *sb = b;
return strcmp(*sa, *sb);
}
A few details matter here:
aandbpoint to elements inside the array of string pointers.strcmp()performs lexicographic comparison.- The result is alphabetical in the usual C sense, not necessarily natural-language sorting.
Common mistakes to avoid
Sorting bugs in C often come from small pointer or loop mistakes rather than the algorithm itself. Watch for these issues:
-
Off-by-one loop bounds
- A loop that goes one step too far can read past the end of the array.
-
Wrong
sizeofcalculationssizeof(arr) / sizeof(arr[0])works only whenarris still an actual array, not a pointer parameter.
-
Incorrect comparison logic in
qsort()- Returning
a - bdirectly can overflow for large integers.
- Returning
-
Forgetting that arrays passed to functions decay to pointers
- Inside a function,
sizeof(arr)usually gives the size of a pointer, not the whole array.
- Inside a function,
-
Swapping with uninitialized temporary values
- Always store the current value before overwriting it.
When to use each method
| Scenario | Recommended choice |
|---|---|
| Learning how sorting works | Bubble sort or selection sort |
| Small arrays, simple code | Insertion sort |
| General-purpose app code | qsort() |
| Custom ordering rules | qsort() with your own comparator |
For most practical C programming, the best pattern is: keep the sort logic separate, define a reusable comparison function, and sort in place unless you need to preserve the original order.
A few practical tips
If your array is very large, algorithm choice matters more than micro-optimizing the swap code. If your data is tiny, readability matters more than advanced optimization. If you need stable ordering, check whether your chosen algorithm preserves equal elements in their original relative order.
A few extra habits make C sorting code easier to maintain:
- Use clear function names like
sort_scoresorcompare_names. - Keep the comparator focused on one ordering rule.
- Test with already sorted data, reverse-sorted data, and duplicate values.
- Print the array before and after sorting when debugging.
Summary
Sorting an array in C comes down to choosing the right tool for the job. Manual sorts like bubble sort and selection sort are helpful for learning the mechanics. qsort() is usually the best choice for practical code because it is flexible, reusable, and already built into the standard library.
Once you understand the pattern, the rest is mostly about matching the comparator to the data type and being careful with pointer arithmetic. That is the part that makes C sorting feel tricky at first and completely routine after a few examples.