C qsort 奇怪的行为

C qsort strange behaviour

我正在尝试执行以下操作:

  1. 为7维数组分配内存
  2. 写前4位
  3. 对这 4 个位置进行排序。
  4. 写剩下的3个位置
  5. 对整个数组进行排序。

我有数组 (1,6,2,3),排序后变成 (1,2,3,6)

然后我写剩下的位置,分别是(1,2,3,6,1,5,1)

排序后,我应该得到 (1,1,1,2,3,5,6),但我却得到了 (6,2,3,1,1,5,1).

代码如下:

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

int comp(const void* a, const void* b);

typedef struct{

    int peso;
 }aresta_;

int main(int argc, const char * argv[]) {

    aresta_* array /*struct array, has field peso of type int*/;
    int dim=7;
    int dim_aux=4;
    int i;

    array = (aresta_*) malloc(dim * sizeof(aresta_));

    array[0].peso=1;
    array[1].peso=6;
    array[2].peso=2;
    array[3].peso=3;


    printf("First sort:\n");
    for(i=0; i<dim_aux; i++)
        printf("%d ",array[i].peso);

    printf("\n");


    qsort(array, dim_aux, sizeof(array[0]), comp);


    for(i=0; i<dim_aux; i++)
        printf("%d ",array[i].peso);

    printf("\n\n");

    array[4].peso=1;
    array[5].peso=5;
    array[6].peso=1;

    printf("Second sort:\n");


    for(i=0; i<dim; i++)
        printf("%d ",array[i].peso);

    printf("\n");

    qsort(array, dim, sizeof(array[0]), comp);

    for(i=0; i<dim; i++)
        printf("%d ",array[i].peso);




    printf("\n");

}

我的补偿函数:

int comp(const void* a, const void* b)
{
    aresta_* a1 = (aresta_*)a;
    aresta_* b1 = (aresta_*)b;
    return a1->peso > b1->peso;
}

输出:

First sort:
1 6 2 3 
1 2 3 6 

Second sort:
1 2 3 6 1 5 1 
6 2 3 1 1 5 1 
Program ended with exit code: 0

我哪里做错了?任何帮助将不胜感激。

int comp(const void* a, const void* b)
{
    aresta_* a1 = (aresta_*)a;
    aresta_* b1 = (aresta_*)b;
    ---->   return a1->peso > b1->peso;  <---- Watch carefully out! What it does!
}

return 行只检查是否大于。如果,

  • a1->peso更大,它returns 1
  • b1->peso更大,它returns 0(这也是不正确的结果,因为零必须等于
  • 值彼此相等的相等情况呢?

你没有检查最后一个案例。你可以用 if-else 这样的情况来写

if(a1->peso > b1->peso) {
//  ....
} else if (a1->peso < b1->peso) {
// ....
} else {
// equality case....
}

或者干脆return a1->peso - b1->peso给出预期的结果

  • > 0好积极
  • < 0如此消极
  • == 0如此平等

根据chux nicely drawing attention to overflow point,可以处理溢出情况。

#include <limits.h>

if ((b1->peso > 0 && a1->peso < INT_MIN + b1->peso) ||
      (b1->peso < 0 && a1->peso > INT_MAX + b1->peso)) {
    /* Handle error */
} else {
    return a1->peso - b1->peso;
}

仅 OP 的功能 returned 0 和 1。

因为前 4 个值的 OP 的 "worked" 是 "luck"。

比较函数需要 return 3 个结果中的 1 个:负数、0 或正数。

The function shall return an integer less than, equal to, or greater than zero if the first argument is considered to be respectively less than, equal to, or greater than the second.
C11dr §7.22.5.2 3

int comp(const void* a, const void* b)
{
    const aresta_* a1 = (const aresta_*)a;
    const aresta_* b1 = (const aresta_*)b;
    // return a1->peso > b1->peso;
    return (a1->peso > b1->peso) - (a1->peso < b1->peso);
}

return (a1->peso > b1->peso) - (a1->peso < b1->peso);return a1->peso - b1->peso; 有优势。这个答案不会溢出。它对所有 int 对都有效且功能正确。各种编译器都能识别这个习惯用法并生成紧凑的代码。 int - int 可以溢出,这是 未定义的行为 ,UB。