Qsort 及其相关问题
Posted
技术标签:
【中文标题】Qsort 及其相关问题【英文标题】:Qsort and issues with it 【发布时间】:2013-04-03 05:29:36 【问题描述】:以下是我的代码,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
虽然它应该与输入相同。有人可以解释一下为什么会这样以及我该如何纠正吗?
【问题讨论】:
我不敢相信。一个完全独立、可编译的示例!先生,您应该为此获得勋章! +1,如果可以的话,还有更多。 好点子,@DevSolar,我们应该奖励这样的问题。 【参考方案1】:return ( *(int*)a - *(int*)b );
如果底层“对象”是char
值,则您应该不比较int
值。
几乎可以肯定的是,比较使用四个(取决于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
(我交换了代码中最后两个元素的顺序,以表明它实际上是在排序)。
【讨论】:
"这会极大地阻塞进程。" -- 是的......在排序过程中,被排序的值实际上会发生变化! 如果 OP 对无符号字符进行排序,return *(unsigned char *)a - *(unsigned char *) b
是否会出错,因为减法永远不会产生否定结果?
好点@Adrian,修改文本以说明它们应该在减法之前升级为signed int
。虽然,即使在那里,你也可能会遇到奇怪的架构问题,这些架构对于 char 和 int 具有相同的大小(不太可能)。
@paxdiablo compare 返回一个 int,所以 return *(unsigned char *)a - *(unsigned char *)
会产生负结果,因为它被计算为 int。【参考方案2】:
将比较功能更改为
int compare (const void * a, const void * b)
return ( *(char*)a - *(char*)b );
【讨论】:
以上是关于Qsort 及其相关问题的主要内容,如果未能解决你的问题,请参考以下文章