You should implement your own comparator function and pass it in. The most important (non-trivial) thing to keep in mind here is that according to the standard,
The implementation shall ensure that the first argument is always a pointer to the key.
This means that you can write a comparator that compares a string such as target and a dictionary_t object. Here is a simple function that compares your stucts to a string:
int compare_string_to_dict(const void *s, const void *d) {
return strncmp(s, ((const dictionary_t *)d)->word, sizeof(((dictionary_t *)0)->word));
}
You would then pass it by name as a normal function pointer to bsearch:
result = bsearch(target, dictionary, dict_length, sizeof(dictionary_t), compare_string_to_dict);
Note that target does not need to have its address passed in since it is no longer mocking a struct.
In case you are wondering, sizeof(((dictionary_t *)0)->word) is an idiomatic way of getting the size of word in dictionary_t. You could also do sizeof(dictionary[0].word) or define a constant equal to 30. It comes from here.