【问题标题】:How can I cast a const void* to a struct element?如何将 const void* 强制转换为结构元素?
【发布时间】:2016-09-24 18:59:23
【问题描述】:

我的比较函数可以在 qsort() 中使用,如下所示:

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;
}

我的结构如下:

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

我在函数比较中尝试了许多“强制转换”变体,但都失败了。我的问题很明显,如何将 const void* 强制转换为我的结构元素?我知道这似乎是一个非常基本的问题,但我在任何地方都找不到明确的答案,我也是新手。任何帮助都将不胜感激。

【问题讨论】:

  • a = *(interval*)p; 可能就是你的意思。
  • 您不能转换为 struct 类型或从 struct 类型转换。您可以将void* 转换为指针类型或从指针类型转换。 (事实上​​,转换可以隐式完成,无需强制转换。)
  • 你到底为什么要这样做?丢弃参数中的所有类型信息,然后将数据视为特定类型是一种可怕的做法。如果有人用指向不同类型的指针调用它(没有什么能阻止任何人这样做!)这将导致各种问题。为什么不直接采用实际结构类型的 const ref 参数?
  • @chux 这似乎是考虑重叠间隔相等的间隔排序。这是一个无效的排序比较器,因为您可以有compar(a, b) == 0 &amp;&amp; compare(b, c) == 0compar(a, c) == -1 的间隔。

标签: c struct void-pointers qsort


【解决方案1】:

你很亲密……

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;
}

顺便说一句,没有一个演员,这将在gcc -Wall.下完全干净

更新... Tavian 提出了一个很好的观点,这不是传递顺序,所以您的集合在技术上具有 no partial order. 但根据您的数据和您的目标,qsort 可能会返回一个有用的结果。

【讨论】:

    【解决方案2】:

    qsort() 函数将使用指向元素的指针调用您的回调。

    假设数组是interval 的实际数组,而不是区间指针之一,你会这样做:

    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];
    }
    

    我不理解 extrem 索引,但这是您使用的。将void * 转换为更具体的类型时不需要强制转换。见this answer

    【讨论】:

    • 这是一个一维问题,考虑到任何重叠都是相等的,并且不等式是有序的。顺便说一句,正如现在所写的那样,它不会编译。
    • @DigitalRoss 谢谢,已修复。
    猜你喜欢
    • 2019-08-25
    • 2011-02-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-04-12
    • 1970-01-01
    相关资源
    最近更新 更多