Skip to Content
Course content

90: Searching with bsearch

Click on the "Edit" button in the top corner of the screen to edit your slide content.

You might be tempted to think of bsearch as a general-purpose "find" tool—a more efficient version of a for loop that scans an array for a specific value. I've seen many developers drop bsearch into a project thinking it's just a performance upgrade over a linear search. This is a dangerous assumption.

Thinking bsearch works on any array

Here is the reality: if you pass an unsorted array to bsearch, the function will not "sort it for you," nor will it reliably find your data. It will simply fail, often returning NULL even when the item is sitting right there in the array. Let me show you why.

#include 
#include 
#include 

int compare_ints(const void *a, const void *b) {
    return (*(int*)a - *(int*)b);
}

int main() {
    // Unsorted array
    int numbers[] = {10, 5, 20, 2, 15}; 
    int key = 5;
    
    int *item = bsearch(&key, numbers, 5, sizeof(int), compare_ints);
    
    if (item == NULL) {
        printf("Not found!\n"); // This will likely print, even though 5 is in the list.
    }
    return 0;
}

Binary search works by jumping to the middle of the range and deciding whether to go left or right. If the array isn't sorted, that decision is based on a lie. The algorithm might look at the middle element, see that 5 is smaller than 20, and discard the entire right half of the array—which might be exactly where your target was hiding. It's fast precisely because it ignores most of the data; if that data isn't ordered, the logic collapses.

The strict requirement for pre-sorted data

To use bsearch, your data must be sorted according to the same comparison logic you pass into the function. In professional C code, bsearch is almost always paired with qsort. If the data is static, you sort it once at startup. If it's dynamic, you have to weigh the cost of sorting against the speed of the search.

I usually tell people to think of it as a contract: bsearch promises O(log n) speed, but in exchange, you promise that the array is already ordered. If you break that contract, the behavior is undefined in practice (though usually it just returns NULL).

Handling the generic void pointers

One of the clunkiest parts of bsearch is the void * signatures. Because the function is designed to work with any data type—integers, strings, or complex structs—it doesn't know what it's actually comparing. You have to do the casting yourself inside the comparison function.

Let's look at a real-world example. Suppose we have a list of Employee records and we want to find one by their ID number.

typedef struct {
    int id;
    char name[50];
} Employee;

int compare_employees(const void *a, const void *b) {
    const Employee *empA = (const Employee *)a;
    const Employee *empB = (const Employee *)b;
    
    // Return negative if A < B, zero if A == B, positive if A > B
    return (empA->id - empB->id);
}

// ... inside main ...
Employee staff[] = { {101, "Alice"}, {105, "Bob"}, {110, "Charlie"} };
Employee key = {105, ""}; // We only care about the ID for the search

Employee *found = bsearch(&key, staff, 3, sizeof(Employee), compare_employees);

if (found) {
    printf("Found employee: %s\n", found->name);
}

Notice a few critical details here. First, the key is a full Employee struct. bsearch expects the key to be of the same type as the elements in the array. Second, the comparison function casts those void * pointers back to Employee * before accessing the id field. This is the "C way"—it's not as pretty as generics in other languages, but it's incredibly powerful once you stop fighting the syntax.




📋 Practical Task

Implementing a High-Speed Product SKU Lookup

You are building a warehouse management system. You have an array of Product structs, each containing a sku (an integer) and a price (a float). The products are currently provided to you in a random order.

Your task:

  • Define a Product struct.
  • Create an unsorted array of at least 5 products.
  • Write a comparison function compatible with both qsort and bsearch.
  • Sort the array using qsort.
  • Implement a search that takes a SKU number from the user (or a hardcoded variable) and uses bsearch to find the corresponding product.
  • Print the price of the product if found, or a "Product not found" message if it isn't.
Rating
0 0

There are no comments for now.

to be the first to leave a comment.