Question

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?

Was it helpful?

Solution

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.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top