Fixing the code
Your code passes things of the wrong type to lfind
. If the key
argument is a pointer to some type T, then the base
argument must be a pointer to an array of T. When you pass buffer
as key
, then buffer
, which is an array of char
, is automatically converted to a pointer to char
. Thus, T
is char
. So base
is required to be an array of char
. However, your base
is an array of pointers to char
, so it is the wrong type.
To fix this, add this code in Unique
, after buffer
is defined:
char *BufferPointer = buffer;
Then, to call lfind
, use:
if (!lfind(&BufferPointer, &array, &count, sizeof(char*), StringPtrCompare))
With this call, the first parameter is a pointer to a pointer to char
. Thus, the type T is pointer to char
. This matches &array
, which is a pointer to an array of pointer to char
.
Then, in StringPtrCompare
, the parameters ptr1
and ptr2
will each have type pointer to T. Since T is pointer to char
, the type of ptr1
and ptr2
is pointer to pointer to char
. (I am ignoring the const
qualifier for now.) Then you can call strcmp
this way:
int StringPtrCompare(const void *ptr1, const void *ptr2)
{
return strcmp(* (char **) ptr1, * (char **) ptr2);
}
Pointers to arrays versus pointers to pointers
A pointer to an array, such as char (*)[]
, is not the same things as a pointer to a pointer, such as char **
. If p
is a pointer to an array, then, at the place where p
points, there must be an array of elements: The data of the elements must be at that location.
In contrast, if p
is a pointer to a pointer, then, at the place where p
points, there must be a pointer: The bytes at that location must contain the value of a pointer.
An array versus the address of an array
When buffer
has type char [200]
, it is an array of char
. When you use an array in an expression, it is converted to a pointer to its first element, unless it is the operand of sizeof
, _Alignof
, or &
or is a string literal used to initialize an array. When you pass buffer
to lfind
, none of those exceptions applies, so buffer
is converted to the address of its first char
.
When you pass &buffer
, this expression is the address of the array. The address of the array has the same value as the address of its first element, but has a different type. However, when you pass either buffer
or &buffer
to lfind
, it is converted to void *
, because lfind
is declared to take an argument of that type. Thus, the difference between the types of buffer
and &buffer
is lost, and only the value is passed. Since they have the same value, there is no difference.