6

以下是我的代码和 Qsort 产生奇怪的结果:

#include <stdio.h>
#include <stdlib.h>

char values[] = { 0x02,0x04,0x0b,0x16,0x24,0x30,0x48,0x6c};

int compare (const void * a, const void * b)
{
    return ( *(int*)a - *(int*)b );
}

int main ()
{

    int i;

    qsort (values, 8, sizeof(char), compare);

    for (i = 0; i < 8; i++)
    {
       printf ("%0x ",values[ i ]);
    }
    return 0;
}

这个程序的输出是:

2 6c 48 30 24 4 b 16

尽管它应该与输入相同。有人可以解释为什么会这样以及我该如何纠正吗?

4

2 回答 2

11
return ( *(int*)a - *(int*)b );

如果int底层“对象”是值,则不应比较char值。

几乎可以肯定的是,比较使用四个(取决于sizeof(int))字节进行比较,例如第一个对象是0x02040b16(当然取决于您的字节序)。这将极大地充实该过程。

将其更改为:

return ( *(char*)a - *(char*)b );

然后再试一次。

请注意,签名char是一个实现问题。您可能会发现0x80最终小于0x7f. 如果这不是您想要的,请unsigned char显式使用来提取值,然后在进行减法之前将它们升级为有符号整数(使用另一个强制转换)。

事实上,为了可移植性,您可能还想signed char明确地使用另一种情况。

以下程序显示了它如何使用正确的基础数据类型:

#include <stdio.h>
#include <stdlib.h>

signed char values[] = {0x02, 0x04, 0x0b, 0x16, 0x24, 0x30, 0x6c, 0x48};

int compare (const void *a, const void *b) {
    return *(signed char*)a - *(signed char*)b;
}

int main (void) {
    int i;

    qsort (values, 8, sizeof (char), compare); // char okay here.
    for (i = 0; i < 8; i++)
       printf ("%0x ", values[i]);
    putchar ('\n');

    return 0;
}

这个的输出是:

2 4 b 16 24 30 48 6c

(我交换了代码中最后两个元素的顺序,以表明它实际上是在排序)。

于 2013-04-11T06:04:00.313 回答
4

将您的比较功能更改为

int compare (const void * a, const void * b)
{
    return ( *(char*)a - *(char*)b );
}
于 2013-04-11T06:05:12.693 回答