l.arlev
l.arlev

Reputation: 43

How can I cast a const void* to a struct element?

I have my comparison function to use in qsort() like this:

int compar(const void *p, const void *q){
    interval a,b;

    *p = (interval)a
    *q = (interval)b;

    if(a.extrem[1] < b.extrem[0])
        return -1;
    if(b.extrem[1] < a.extrem[0] )
        return 1;

    return 0;
}

My structure is as follows:

typedef struct interval{
    double extrem[2];
    } interval;

I've tried many variations of "casting" in function compar, which all failed. My question, as it is apparent, how can I cast a const void* to my struct element? I know it seems to be a very basic question but I could not find a clear answer anywhere, also I'm new to this. Any help is gladly appreciated.

Upvotes: 4

Views: 3993

Answers (2)

DigitalRoss
DigitalRoss

Reputation: 146073

You were close...

typedef struct interval {
  double extrem[2];
} interval;

int compar(const void *p, const void *q) {
  const interval *a = p, *b = q;

  if(a->extrem[1] < b->extrem[0])
    return -1;
  if(b->extrem[1] < a->extrem[0])
    return 1;
  return 0;
}

BTW, without a single cast, this will be perfectly clean under gcc -Wall.

Update... Tavian makes a good point, this is not a transitive ordering, so your set technically has no partial order. But depending on your data and your objective, qsort may return a useful result even so.

Upvotes: 4

unwind
unwind

Reputation: 399843

The qsort() function is going to call your callback with pointers to the elements.

Assuming the array is an actual array of interval, not one of interval pointers, you'd do:

static int interval_compare(const void *a, const void *b)
{
  const interval *ia = a, *ib = b;

  if(ia->extrem[1] < ib->extrem[0]) return -1;
  return ib->extrem[1] > ia->extrem[0];
}

I don't understand the extrem indexes, but that's what you used. No casts are necessary when converting void * to a more specific type. See this answer.

Upvotes: 1

Related Questions