【问题标题】:Sorting an array of pointers对指针数组进行排序
【发布时间】:2014-05-16 19:16:18
【问题描述】:

我是否认为可以将指针视为 int 以便对指针数组进行排序,例如

qsort(ptrs, n, sizeof(void*), int_cmp);

我想对 ptrs 进行排序以确定是否有任何重复项,而不管指针指向的事物的类型,所以 qsort 是这样做的前兆。

我的int_cmp() 非常标准,例如

int int_cmp(const void *a, const void *b)
{
    const int *ia = (const int *)a; // casting pointer types
    const int *ib = (const int *)b;

    /* integer comparison: returns negative if b > a
    and positive if a > b */
    return *ia  - *ib;
}

它似乎在我的单元测试中有效,但是否有某些原因将 ptr 视为 int 可能会导致我可能忽略的这种情况出现问题?

【问题讨论】:

  • 不,您不能将指针视为int。指针的大小可能与int 的大小不同。还要记住,有许多类型的数据不能直接比较,也不能用于算术表达式(例如结构)。
  • 只有intptr_tuintptr_t 是保证能够保存指针的整数变量。
  • 应该是const int *ia = *(const int **)a; const int *ib = *(const int **)b;
  • 那么,当int 的数组而不是int * 的数组时,你会怎么做?
  • 我的示例 cmp 函数用于整数数组指针数组,例如qsort(ptrs, n, sizeof(void*), int_cmp); 使用int_cmp 表示指针数组。

标签: c sorting pointers


【解决方案1】:

不,你根本不对,除非你想要按地址对指针进行排序。但是,实际地址很少有任何意义,所以这不太可能。

为了检测重复的指针,你应该只比较指针,这是明确的。

我可能会选择使用uintptr_t 的解决方案:

static int order_pointers(const void *pa, const void *pb)
{
  const uintptr_t a = *(void **) pa, b = *(void **) pb;

  return a < b ? -1 : a > b;
}

尚未对此进行测试,但类似的东西应该可以工作。

转换为uintptr_t 是必要的,因为您无法有效地比较随机指针。我引用了 C99 草案标准,§6.5.8.5:

当比较两个指针时,结果取决于指针中的相对位置 指向的对象的地址空间。如果两个指向对象或不完整类型的指针都 指向同一个对象,或者都指向同一个数组对象的最后一个元素, 他们比较相等。如果指向的对象是同一个聚合对象的成员, 指向稍后声明的结构成员的指针比较大于指向成员的指针 在结构的前面声明,以及指向具有较大下标的数组元素的指针 值比较大于指向具有较低下标的同一数组的元素的指针 价值观。所有指向同一个联合对象成员的指针比较相等。如果 表达式 P 指向数组对象的元素,表达式 Q 指向 同一个数组对象的最后一个元素,指针表达式Q+1比较大于 P. 在所有其他情况下,行为未定义。

我将最后一句加粗,因为这适用于这里。

【讨论】:

  • 是的,这正是我想要做的 - 按 address 排序,然后评估我是否在数组中有重复的 ptrs,例如2 个相同的地址
  • 为什么要转换成整数?请参阅 TripeHound 的答案。
  • @alk 因为未定义的行为。 :)
  • 我很高兴我问了最初的问题 - 毕竟它不是那么简单.. 我应该发布更大的问题,'如何删除重复的 ptrs,即指向相同的底层对象,以独立于底层对象的通用方式来自一组 ptrs..
  • @unwind 顺便说一句,您的默认方法是使函数静态化吗?我原以为你会想在许多文件中使用这样的 cmp 函数?
【解决方案2】:

如果您使用比较而不是减法,您可以坚持使用 void 指针:以下适用于简单测试:

int int_cmp( const void *pa, const void *pb )
{
    const void* a = *(void**)pa ;
    const void* b = *(void**)pb ;

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

【讨论】:

  • -1,这是未定义的行为。不要过度吹嘘自己的号角,但是……看我的回答。
  • @alk 是的,除非您知道指针指向(或超出)同一个“对象”,否则请参阅我的回答中的标准引用。
  • @unwind:我不研究(或阅读)标准,所以很高兴向更深入的知识低头,但是如果比较两个可能指向任何东西的指针是未定义的,那么如何转换它们整数更明确?
  • @TripeHound C 不保证指针被编码为纯整数。例如,可能有分段内存在起作用。对于这样的架构,编译器在转换为整数时必须巧妙地“展平”空间,以便不同的指针变成不同的整数。据我所知,可以比较的整数没有限制。
  • 并且在 [this_answer]{stackoverflow.com/questions/1845482/what-is-uintptr-t-data-type} 中他们引用:在 C99 中,它被定义为“具有任何指向 void 的有效指针都可以转换为此属性的无符号整数类型类型,然后转换回指向 void 的指针,结果将与原始指针进行比较”。 这是否意味着比较 intptr_t 也是未定义的(您所能做的就是将它们转换回 void 指针?)
猜你喜欢
  • 2014-03-11
  • 2017-05-07
  • 2013-08-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-02-25
相关资源
最近更新 更多