以下是我的代码,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
虽然它应该与输入相同.有人可以解释为什么会这样,以及我如何纠正它?
解决方法
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,0x6c,0x48}; int compare (const void *a,const void *b) { return *(signed char*)a - *(signed char*)b; } int main (void) { int i; qsort (values,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
(我交换了代码中最后两个元素的顺序,以表明它实际上是在排序某些东西).