Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/58.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C 对指针数组进行排序_C_Sorting_Pointers - Fatal编程技术网

C 对指针数组进行排序

C 对指针数组进行排序,c,sorting,pointers,C,Sorting,Pointers,我认为,为了对指针数组进行排序,可以将指针视为int吗 qsort(ptrs, n, sizeof(void*), int_cmp); 我想对ptr进行排序,以确定是否存在任何重复项,而不管指针指向的是什么类型的对象,因此qsort是这样做的前提 我的int\u cmp()非常标准,例如 int int_cmp(const void *a, const void *b) { const int *ia = (const int *)a; // casting pointer types

我认为,为了对指针数组进行排序,可以将指针视为int吗

qsort(ptrs, n, sizeof(void*), int_cmp);
我想对ptr进行排序,以确定是否存在任何重复项,而不管指针指向的是什么类型的对象,因此qsort是这样做的前提

我的
int\u 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可能会在我可能忽略的情况下导致问题?

不,你完全不对,除非你想按地址对指针排序。然而,实际地址很少有任何意义,所以这是不太可能的

为了检测重复的指针,您应该只比较指针本身,这是定义良好的

我可能会使用
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;
}
static int order_指针(const void*pa,const void*pb)
{
常数a=*(void**)pa,b=*(void**)pb;
返回ab;
}
我还没有测试过这个,但是类似的东西应该可以用

由于无法有效比较随机指针,因此有必要将其转换为
uintptru\t
。我引用C99标准草案第6.5.8.5节:

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


我把最后一句加粗了,因为这在这里是适用的

如果您使用比较,而不是减法,您可以使用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 ;
}
int-int\u-cmp(常数无效*pa,常数无效*pb)
{
常数void*a=*(void**)pa;
常数void*b=*(void**)pb;
如果(ab)返回1;
返回0;
}

不,不能将指针视为
int
。指针的大小可能与
int
的大小不同。还要记住,有许多类型的数据不能直接比较,也不能用在算术表达式中(例如结构)。保证能够保存指针的唯一整数变量是
intptr\u t
uintptr\u t
。应该是
const int*ia=*(const int**)a;常数int*ib=*(常数int**)b那么,当一个
int
数组而不是
int*
数组时,你会怎么做?我的示例cmp函数用于一个int数组:指针数组,例如qsort(ptrs,n,sizeof(void*),int\u cmp);用于指针数组的
int\u cmp
。是的,这正是我想要做的-按地址排序,以便评估数组中是否有重复的PTR,例如,2个相同的地址为什么要转换为整数?请参阅TripeHound的答案。@alk因为未定义的行为。:)我很高兴我问了最初的问题-毕竟不是那么简单。。我可能应该发布一个更大的问题,“如何以一种通用的方式从一个PTR数组中移除重复的PTR,即指向相同底层对象的PTR,而不依赖于底层对象。@unwind作为一个旁白,您的默认方法是使函数成为静态的吗?”?我原以为您会希望在许多文件中使用这样的cmp函数?-1,这是未定义的行为。不是为了吹响我自己的号角,但是。。。请看我的答案。@alk Yes,除非你知道指针指向(或刚好超出)同一个“对象”,请看我答案中的标准引文。@REWIND:我不研究(或阅读)标准,所以我很乐意向更深的知识低头,但如果比较两个可能指向任何东西的指针是未定义的,如何将它们转换为整数才能得到更好的定义?@TripeHound C不能保证指针只编码为普通整数。例如,可能存在分段内存。对于这样的体系结构,编译器必须在转换为整数时插入聪明度,以“展平”空间,使不同的指针变成不同的整数。据我所知,整数之间的比较是没有限制的。在[this_answer]{}中,他们引用了:在C99中,它被定义为“一种无符号整数类型,其属性是任何指向void的有效指针都可以转换为这种类型,然后再转换回指向void的指针,结果将与原始指针相等”。那么,这是否意味着比较intptr\t也没有定义(您所能做的就是将它们转换回void指针?)