I have a struct:
typedef struct DATA {
char *key;
char *parentKey;
char *description;
} DATA;
And an array of instances:
DATA *data_array = NULL; // the global data array
int m_arrayLength = 0; // Keeps track of the number of elements used
Once the array is populated I am sorting it using qsort
void SortData()
{
qsort(data_array, m_arrayLength, sizeof(DATA), CompareDataByKey);
}
int CompareDataByKey(const void *a, const void *b)
{
DATA *ia = (DATA *)a;
DATA *ib = (DATA *)b;
return strcmp(ia->key, ib->key);
}
And this is working as expected. I'm trying to implement a method that searches the array for a particular item and this is where I am stuck
DATA FindDataByKey(char *key)
{
DATA *searchData = malloc(sizeof(DATA));
searchData->key = key;
DATA result = bsearch(
searchData,
data_array,
m_arrayLength,
sizeof(DATA),
CompareDataByKey);
free(searchData);
return result;
}
The gcc
compiler is returning the message:
p_CONNECT.c: In function 'FindDataByKey':
p_CONNECT.c:87: error: invalid initializer
make: The error code from the last command is 1.
on line CompareDataByKey);
Can anyone explain the meaning of this error in the context of the code I have written?
You are thrown off by the line number reported by the compiler. The "incorrect initializer" message refers to the whole DATA result = bsearch(...)
initialization/expression, which ends with the last argument, and not to the last argument itself.
Initializer is incorrect because result
is declared as DATA
(a struct), and bsearch
returns a pointer. To fix it, declare result
as a pointer:
DATA *result = bsearch(
searchData,
data_array,
m_arrayLength,
sizeof(DATA),
CompareDataByKey);
When you fix that, you must also change FindDataByKey
to return DATA *
, not DATA
. Several unrelated coding remarks:
You don't need to malloc
the search data when calling bsearch
, you can just initialize it on the stack and pass the address of the variable to the function. For example:
DATA searchData;
searchData.key = key;
return bsearch(&searchData, ...);
If you call malloc
, don't forget to check its return value. A call to malloc
can fail, and it is a good idea to report this failure to the user. (The customary way of doing that is by creating a wrapper called something like xmalloc
, which calls malloc
, checks its result, and prints an error message and calls exit()
if the result is NULL.)
Prefixing a global variable with m_
will confuse users coming from a C++ background, where the m_
prefix denotes class members.