qsort() in C Programming: Syntax, Examples & Uses

Complete Guide to qsort() in C Programming

Introduction to qsort() in C

Sorting is a fundamental operation in C programming that organizes data in ascending or descending order, making searching, analysis, and data processing easier. From arranging sensor readings in embedded systems to sorting student marks, product prices, transaction records, and communication logs, sorting is essential in many software applications. C provides the standard library function qsort() to sort arrays without requiring developers to implement a complete sorting algorithm manually.

The qsort() function supports generic sorting through pointers, element sizes, and a user-defined comparison function. This makes it suitable for integers, floating-point values, strings, structures, and custom data records. Understanding qsort() also strengthens knowledge of C pointers, void pointers, function pointers, arrays, structures, and memory representation—important concepts for system programming and embedded software development.

For learners pursuing professional C programming and embedded systems training, Embedded Tech Development Academy (ETDA) emphasizes technical concepts that help students develop practical programming skills. Aspiring developers exploring the Top Embedded Training Institute in Bangalore can benefit from learning standard C library functions, memory handling, and data organization. This guide explains the syntax, working principles, comparison logic, practical examples, complexity, common mistakes, and applications of qsort() in detail.

What Is qsort() in C Programming?

qsort() is a standard C library function declared in the stdlib.h header file. It sorts an array using a comparison function supplied by the programmer.

#include <stdlib.h>

Although its name suggests Quick Sort, the C standard does not require every implementation to use the Quick Sort algorithm. The internal sorting method is implementation-dependent, so developers should not assume a particular algorithm or worst-case complexity without consulting the relevant library documentation.

Why Is qsort() Useful?

The function provides several advantages:

  • Generic sorting: Supports arrays containing different data types.

  • Custom ordering: Allows ascending, descending, or field-based sorting.

  • Code reuse: Avoids implementing a separate sorting algorithm for each data type.

  • Standard availability: Supported by standard C libraries.

  • Flexible records: Can sort structures using selected fields.

Syntax of qsort()

void qsort(
    void *base,
    size_t nmemb,
    size_t size,
    int (*compar)(const void *, const void *)
);

Understanding the Parameters

  1. base – Pointer to the first element of the array.

  2. nmemb – Number of elements to sort.

  3. size – Size of each element in bytes, usually obtained using sizeof.

  4. compar – Pointer to the function that compares two elements.

Important Parameter Consideration

Always calculate the array length correctly when the array is available in the same scope:

int arr[] = {8, 3, 1, 7, 0};
size_t n = sizeof(arr) / sizeof(arr[0]);

This calculation does not work as intended when arr is a pointer to dynamically allocated memory or when an array has been passed to a function as a pointer. In those situations, pass the element count separately.

How the qsort() Comparison Function Works

The comparison function determines the order of elements. It receives pointers to two array elements and returns an integer indicating their relative order.

int compare(const void *a, const void *b);
  • Negative value: The first element belongs before the second.

  • Zero: Both elements are equivalent for the selected sorting criterion.

  • Positive value: The first element belongs after the second.

Because the parameters are const void *, the comparison function must interpret them using the correct element type.

Example 1 — Sorting Integers in Ascending Order

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

int compare_int(const void *a, const void *b)
{
    int x = *(const int *)a;
    int y = *(const int *)b;

    if (x < y) return -1;
    if (x > y) return 1;
    return 0;
}

int main(void)
{
    int arr[] = {8, 3, 1, 7, 0, 10, 2};
    size_t n = sizeof(arr) / sizeof(arr[0]);

    qsort(arr, n, sizeof(arr[0]), compare_int);

    for (size_t i = 0; i < n; i++)
        printf("%d ", arr[i]);

    printf("\n");
    return 0;
}

Output:

0 1 2 3 7 8 10

The comparison function converts each generic pointer to const int *, dereferences it, and compares the resulting integer values. The array is sorted in place.

Example 2 — Sorting Integers in Descending Order

Reverse the comparison conditions to sort from largest to smallest:

int compare_desc(const void *a, const void *b)
{
    int x = *(const int *)a;
    int y = *(const int *)b;

    if (x > y) return -1;
    if (x < y) return 1;
    return 0;
}

Pass compare_desc as the fourth argument to qsort(). Avoid returning y - x or x - y directly because signed integer subtraction can overflow.

Example 3 — Sorting Floating-Point Values

Floating-point values should be compared using relational operators rather than subtraction, which may lose precision or behave unexpectedly for special values.

int compare_float(const void *a, const void *b)
{
    float x = *(const float *)a;
    float y = *(const float *)b;

    if (x < y) return -1;
    if (x > y) return 1;
    return 0;
}

For applications that may contain NaN values, define an explicit ordering policy because ordinary comparisons with NaN do not behave like comparisons between normal numbers.

Example 4 — Sorting Strings

An array of strings is commonly represented as an array of pointers to character sequences. The comparison function must therefore dereference each argument to obtain the corresponding string pointer.

#include <stdlib.h>
#include <string.h>

int compare_strings(const void *a, const void *b)
{
    const char *x = *(const char * const *)a;
    const char *y = *(const char * const *)b;

    return strcmp(x, y);
}

Call qsort(strings, count, sizeof(strings[0]), compare_strings); to sort the string pointers in lexicographical order. strcmp() compares strings according to the character values; it does not automatically provide locale-aware alphabetical ordering.

Example 5 — Sorting Structures by Marks

Structures can be sorted using one field, such as student marks, employee IDs, timestamps, or product prices.

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

struct Student {
    int marks;
};

int compare_marks(const void *a, const void *b)
{
    const struct Student *x = a;
    const struct Student *y = b;

    if (x->marks < y->marks) return -1;
    if (x->marks > y->marks) return 1;
    return 0;
}

int main(void)
{
    struct Student s[] = {{75}, {90}, {65}, {85}};
    size_t n = sizeof(s) / sizeof(s[0]);

    qsort(s, n, sizeof(s[0]), compare_marks);

    for (size_t i = 0; i < n; i++)
        printf("%d ", s[i].marks);

    return 0;
}

Output:

65 75 85 90

The comparison function interprets each pointer as a pointer to struct Student and compares the marks member. The complete structures are rearranged, not just their marks fields.

qsort() Performance and Common Errors

How Does qsort() Work Internally?

The C standard specifies the sorting behavior but does not mandate the internal algorithm. A library implementation may use Quick Sort, merge-sort-based techniques, heapsort, or another suitable method.

Understanding Sorting Complexity

For an implementation based on Quick Sort, typical complexity is (O(n \log n)) on average, with a possible (O(n^2)) worst case for some implementations and pivot strategies. These are not universal guarantees for every qsort() implementation. Consult the library documentation when strict performance bounds are necessary.

Common Mistakes to Avoid

  • Incorrect element size: Use sizeof(arr[0]) or sizeof(type) for the actual element type.

  • Wrong pointer interpretation: Cast or assign each const void * to the correct pointer type before dereferencing.

  • Subtraction overflow: Use relational comparisons for integers instead of returning x - y.

  • Inconsistent comparisons: The comparator must provide a consistent ordering; contradictory results can cause incorrect behavior.

  • Assuming stable sorting: qsort() does not guarantee that equal elements retain their original order.

  • Sorting the wrong representation: For strings, distinguish between an array of characters and an array of string pointers.

Applications of qsort() in Embedded and General C Programming

qsort() is useful in data processing, academic software, financial applications, and system utilities. Developers may sort sensor samples, diagnostic records, product lists, event timestamps, or test results.

In embedded systems, it can organize buffered measurements, rank error codes, or process calibration data. However, dynamic memory constraints, execution-time predictability, stack usage, and real-time deadlines must be considered before using a library sorting function in a critical embedded task. For small fixed-size arrays or hard real-time systems, a purpose-built sorting algorithm may be more appropriate.

Building Practical C Programming Skills

Developers should practice sorting arrays, comparing structures, handling pointers safely, and testing edge cases such as empty arrays, duplicate values, negative integers, and already sorted data. Technical learning through Embedded Tech Development Academy (ETDA) can help learners connect C programming fundamentals with embedded firmware concepts. Students researching the Top Embedded Training Institute in Bangalore should look for practical exercises that build confidence in pointers, structures, debugging, and standard library functions.

Frequently Asked Questions

What is qsort() in C?

qsort() is a standard library function declared in stdlib.h that sorts an array using a programmer-supplied comparison function.

No. The C standard does not require a particular sorting algorithm. The implementation may use a different algorithm, so check the relevant library documentation for performance details.

Yes. The comparison function can interpret the input pointers as pointers to a structure and compare selected fields, such as marks, IDs, or prices.

Write a comparison function that returns a negative value when the first element should appear before the second in descending order. Then pass that function to qsort().

No stability guarantee is provided by the C standard. If the relative order of equivalent elements matters, use a stable sorting algorithm or add a suitable tie-breaker when appropriate.

The C standard does not specify a universal time complexity. Many implementations perform around (O(n \log n)) comparisons on average, but performance depends on the implementation and input.

Conclusion

The qsort() function is a flexible standard C library tool for sorting arrays of integers, floating-point values, strings, and structures. Its generic interface uses an array pointer, element count, element size, and comparison function to determine the sorting order. Correct pointer conversion, overflow-safe comparisons, consistent comparator behavior, and accurate element sizes are essential for reliable results. Developers should also understand that the C standard does not guarantee a specific internal algorithm, stable ordering, or universal complexity bounds.

Mastering qsort() strengthens practical C programming, pointer handling, data structures, and system-level development skills. For learners progressing toward embedded firmware development, Embedded Tech Development Academy (ETDA) can be a resource to explore for technical training and assured placement support. Those comparing options for the Top Embedded Training Institute in Bangalore should prioritize hands-on C programming, debugging, microcontroller projects, and real-world coding practice. Combined with consistent exercises, these skills help programmers write clearer and more maintainable applications.

Author: ETDA Trainers
Experience: 10+ Years of Industry Experience in Embedded Systems, IoT, and Embedded C Programming