如何将 const void* 强制转换为结构元素?
Posted
技术标签:
【中文标题】如何将 const void* 强制转换为结构元素?【英文标题】:How can I cast a const void* to a struct element? 【发布时间】: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 参数?
@adam10603 linux.die.net/man/3/qsort
@chux 这似乎是考虑重叠间隔相等的间隔排序。这是一个无效的排序比较器,因为您可以有compar(a, b) == 0 && compare(b, c) == 0
但compar(a, c) == -1
的间隔。
【参考方案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 谢谢,已修复。以上是关于如何将 const void* 强制转换为结构元素?的主要内容,如果未能解决你的问题,请参考以下文章