3

我使我的冒泡排序程序通用。我继续测试它,它运行良好,直到我在数组中放置了一个负数,我很惊讶它被推到最后,使它大于正数。

显然memcmp是这个原因,那么为什么memcmp()认为负数大于正数呢?

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

void bubblesortA(void *_Buf, size_t bufSize, size_t bytes);

int main(void)
{
    size_t n, bufsize = 5;
    int buf[5] = { 5, 1, 2, -1, 10 };
    bubblesortA(buf, 5, sizeof(int));

    for (n = 0; n < bufsize; n++)
    {
        printf("%d ", buf[n]);
    }
    putchar('\n');

    char str[] = "bzqacd";
    size_t len = strlen(str);
    bubblesortA(str, len, sizeof(char));

    for (n = 0; n < len; n++)
    {
        printf("%c ", str[n]);
    }
    putchar('\n');
    return 0;
}

void bubblesortA(void *buf, size_t bufSize, size_t bytes)
{
    size_t x, y;
    char *ptr = (char*)buf;
    void *tmp = malloc(bytes);
    for (x = 0; x < bufSize; x++)
    {
        ptr = (char *)buf;
        for (y = 0; y < (bufSize - x - 1); y++)
        {
            if (memcmp(ptr, ptr + bytes, bytes) > 0)
            {
                memcpy(tmp, ptr, bytes);
                memcpy(ptr, ptr + bytes, bytes);
                memcpy(ptr + bytes, tmp, bytes);
            }
            ptr += bytes;
        }
    }
    free(tmp);
}

编辑
那么,如何修改程序以使其正确比较?

4

4 回答 4

6

memcmp比较字节,它不知道字节是否代表ints, doubles, strings, ...

因此,将字节视为无符号数再好不过了。因为负整数通常使用二进制补码表示,所以设置了负整数的最高位,使其大于任何有符号的正整数。

于 2015-11-25T11:30:45.993 回答
4

回答 OP 的附加编辑

如何修改程序以使其正确比较?

将两种类型作为匿名位模式进行比较,memcmp()效果很好。要比较某种类型的两个值,代码需要该类型的比较函数。跟随qsort() 风格:

void bubblesortA2(void *_Buf,size_t bufSize,size_t bytes, 
    int (*compar)(const void *, const void *)))
{
   ....
        // if(memcmp(ptr,ptr+bytes,bytes) > 0)
        if((*compar)(ptr,ptr+bytes) > 0)
   ....

要比较int,请传入比较int函数。请注意ab是对象的地址。

int compar_int(const void *a, const void *b) {
  const int *ai = (const int *)a;
  const int *bi = (const int *)b;
  return (*ai > *bi) - (*ai < *bi);
}

要进行比较char,请传入一个比较char函数

int compar_int(const void *a, const void *b) {
  const char *ac = (const char *)a;
  const char *bc = (const char *)b;
  return (*ac > *bc) - (*ac < *bc);
}
于 2015-11-25T12:52:17.563 回答
0

负数的符号位(最高有效位)设置为 1。函数memcmp将字节作为无符号值进行比较。因此它将符号位视为值位。结果,有时负数大于正数。

于 2015-11-25T11:33:32.603 回答
0

在计数数字和负数的符号中,第一位用作符号位,指示数字是负数还是正数的位。

如果我们看一下 2 个数字的二进制表示,就会很清楚。值得注意的是,memcmp只需比较 2 个数字,就好像它们都是指定长度的无符号数字一样。

-27 二进制表示法(8 位表示法,二进制补码):1110 0101

+56 二进制:0011 1000

如果您将两者进行比较,就好像它们是正数一样,您会注意到 -27 表示实际上更大。

于 2015-11-25T11:39:12.597 回答