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 );

基礎となる「オブジェクト」が値である場合、値を比較するべきではありませんintchar

ほぼ確実に起こっているのはsizeof(int)、最初のオブジェクトが0x02040b16(もちろんエンディアンネスに応じて)存在するなど、比較が4(に応じて)バイトを使用して比較を行うことです。これはプロセスを大幅に詰め込みます。

次のように変更します。

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

(実際に何かをソートしていることを示すために、コードの最後の 2 つの要素の順序を入れ替えました)。

于 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 に答える